网络知识 娱乐 【CSS】381- 提升你的CSS选择器技巧

【CSS】381- 提升你的CSS选择器技巧

我已经使用CSS多年了,但直到最近我才深入研究了一下CSS选择器。

我为什么要这样做呢?我们都知道选择器,但麻烦的是随着时间的推移,很容易习惯于在每个项目中使用相同的可信任选择器来实现你需要做的事情。

所以我就对CSS选择器进行了深入的回顾,并且遇到了一些有趣的,对我来说是新的或者以前不知道的一些用法。

我还发现了一些很酷的新选择器,将来可用但尚未被广泛支持。

组合选择器

让我们从熟悉的领域开始。组合选择器用于选择后代元素、子元素以及兄弟元素,并且已经存在了很长一段时间。

  • 后代选择器 A B
  • 子元素选择器 A>B
  • 相邻兄弟选择器 A+B
  • 通用兄弟选择器 A~B

相邻兄弟选择器 A+B 你应该很熟悉,选择紧跟在 A 之后的元素 B,但是通用兄弟选择器 A~B 呢? 这将选择所有跟在 A 之后的兄弟元素 B

参看下面的一个例子:

(codepen链接:https://codepen.io/dgwyer/embed/RyvYXd)

New York被选中是因为它紧跟在第一行之后,最后两个城市被突出显示,因为通用兄弟选择器匹配了第四行之后的所有城市。

属性选择器

我非常喜欢属性选择器。当你需要匹配包含具有特定属性值的元素时,它们非常灵活。

(codepen链接:https://codepen.io/dgwyer/embed/MGLZEK)

这个例子演示了如何选择所有 type="checkbox" 的元素并将其关联标签设置样式,使其变为粗体和蓝色。

然后,选择其中 name="chk2" 元素并将其关联标签改为红色。

属性选择器不仅适用于表单元素,它们还可以匹配任何元素的属性,并且在非官方支持的属性上也可应用。此外,还可以检查属性是否存在,参看下面的一个例子:

button[icon]

匹配 <button> 标签中有 icon 属性存在的元素 ,不论 icon 属性是否有值。

更多相关的例子:

(codepen链接:https://codepen.io/dgwyer/embed/pVGGye)

第一个链接没有 target 属性,因此不匹配。 接下来的两个链接是匹配的,因为它们都具有 target 属性,并一个有特定值,一个没有值。 最后一个链接设置为粉红色,因为它具 fluffy 属性。

一个实用的例子,突出显示没有 alt 属性的图像。 此属性是可访问性所必需的,因此对于SEO而言,确保所有图像元素都包含此属性非常重要。

我们可以使用以下代码来实现:

img:not([alt]) {
 border: 2px red dashed;
}

(codepen链接:https://codepen.io/dgwyer/embed/OZdqLp)

如果要匹配属性值部分,则可以使用以下方法。

  • A[attr^=val] 属性值以val开头。
  • A[attr|=val] 属性值等于val或者以“val-”开头;
  • A[attr$=val] 属性值以val结束。
  • A[attr*=val] 属性值中包含了val;
  • A[attr~=val] 属性值是一个词列表,并且以空格隔开,其中词列表中包含了一个val词。

以下包含了相对应的每个例子:

(codepen链接:https://codepen.io/dgwyer/embed/MGLdvE)

前两个实例非常相似,其中 A[attr|=val] 匹配“val-”开头的这个特性,对于匹配语言属性很有用,例如: <plang=“en-us”>

[attr$=val] 可以轻松匹配文件扩展名,并且配合 ::after 把匹配到文件属性值显示在页面上。

A[attr*=val] 无论使用何种协议或子域,都可以匹配到含有 mysite 域名的元素。

最后 A[attr~=val] 它非常适合匹配由空格分隔的属性值,因为它只匹配整个单词而不是单词片段。

以上所有属性选择器实例都区分大小写。 但是我们有一个技巧, 如果我们在结束方括号之前插入一个i,我们可以不区分大小写进行匹配。

(codepen链接:https://codepen.io/dgwyer/embed/LmaYzp)

除Internet Explorer和Microsoft Edge外,大多数主流浏览器都支持这种不区分大小写的匹配方法。

用户界面选择器

如果你处理过表单样式,那么你之前一定遇到过这些伪类选择器:

  • :enabled 启用状态(可激活或获取焦点)的元素。
  • :disabled 禁用状态的元素。
  • :checked 选中状态的元素。

例如,我们使用 :checked 来实现一个简单的待办事项列表。

(codepen链接:https://codepen.io/dgwyer/embed/BxbjoO)

这些是比较常用到的,还有其他一些有趣的伪类选择器。

:default 可以匹配一个或多个元素,这些元素是一组相关元素中默认的元素。

(codepen链接:https://codepen.io/dgwyer/embed/ELMoNK)

下面的伪类选择器可以匹配输入值是否有效,以及在提交表单之前检查必填项是否填写。

  • :valid 内容验证正确的元素。
  • :invalid 内容验证未通过的元素。
  • :required 有required属性的元素(必填项)。
  • :optional 没有required属性的元素(可选项)。

(codepen链接:https://codepen.io/dgwyer/embed/qYvpMP)

工作电子邮件地址是必填项,并且要求填写正确有效;个人工作电子邮件地址不是必需的,但如若填写,需正确有效。还有要注意一点是伪类选择器是可以组合使用,例如: :required:invalid

接下来的两个伪类选择器匹配拥有取值范围(支持 minmax 属性)的元素。

  • :in-range 当前值处于属性 minmax 限定的范围之内。
  • :out-of-range 当前值处于属性 minmax 限定的范围之外。

(codepen链接:https://codepen.io/dgwyer/embed/Jvzpgz)

最后我们再介绍三个伪类选择器: :read-only:read-write:placeholder-shown

(codepen链接:https://codepen.io/dgwyer/embed/ZoPREB)

:read-only 匹配不可被用户编辑或拥有 readonly 属性的元素。 :read-write 匹配可以被用户编辑或拥有 contenteditable 属性的元素。

最后, :placeholder-shown 匹配占位文字处于显示状态的元素,当输入内容后,占位文字不再显示时,该元素将不会被匹配;应谨慎使用此选择器,因为它尚未得到广泛支持。

结构选择器

结构选择器非常强大,它是基于元素在DOM中的位置进行匹配。

这类型选择器特殊的地方在于它允许通过传入参数的方式来操作。

例如: :nth-child() 传入一个参数,通过该参数将匹配特定的元素。

因此,如果我们有一组列表,通过下面的选择器将匹配到位置排序是第三的列表:

ul:nth-child(3)

这个参数不只是数字,它还可以是一个表达式,使得匹配能力更强大。

下面是关于使用参数的多个例子:

  • ul:nth-child(2) 位置排序是第二个的元素。
  • ul:nth-child(4n) 位置排序是 (4, 8, 12, …)的元素。
  • ul:nth-child(2n+1) 位置排序是 (1, 3, 5, …)的元素。
  • ul:nth-child(3n — 1) 位置排序是 (2, 5, 8, …)的元素。
  • ul:nth-child(odd) 位置排序是奇数的元素 (1, 3, 5, …)。
  • ul:nth-child(even) 位置排序是偶数的元素 (2, 4, 6, …)。

其中 n 是从零开始,然后 n 为1,再 n 为2,依此类推匹配所有符合表达式的元素。

结构选择器中使用参数来做匹配的选择器如下:

  • :nth-child() 正序匹配某个元素的一个或多个子元素。
  • :nth-last-child() 倒序匹配某个元素的一个或多个子元素。
  • :nth-of-type() 正序匹配某个元素的一个或多个特定类型子元素。
  • :nth-last-of-type() 倒序匹配某个元素的一个或多个特定类型子元素。

(codepen链接:https://codepen.io/dgwyer/embed/MGxzEq)

你可以对选择器做各种不同组合,例如上面的例子里一个代码片段:

ul:last-of-type li:nth-last-of-type(2)::after {
  content: “ (2nd from end)”;
  /* Other styles… */
}

它匹配是一个排序倒数第二个 li 标签的伪元素,从属于最后一项 ul 中。当你面对一个复杂的选择器,可以尝试从右往左阅读它,这样有助与能更好的理解它。

接下来的一组结构选择器,它们仅匹配特定的子元素,您无法通过传递参数给它们以修改其行为。

  • :first-child 匹配某个元素的第一个子元素。
  • :last-child 匹配某个元素的最后一个子元素。
  • :only-child 匹配某个元素的唯一一个子元素。
  • :first-of-type 匹配某个元素的第一个特定类型子元素。
  • :last-of-type 匹配某个元素的最后一个特定类型子元素。

(codepen链接:https://codepen.io/dgwyer/embed/JvzwJE)

咋一看,内容样式是无序纷杂的;你在使用这些类型的选择器时要小心,因为你可能得到你没想到的结果。

例如,你可能想知道为什么 <section> 里只有“And so on…”这段文本是蓝色的,实际上 <section> 里文本都本应该是蓝色的,只是其他元素被不同的选择器覆盖了颜色,才造成只有一段文本是蓝色。

内容选择器

这些是目前可以直接使用的内容选择器:

  • ::first-line 匹配元素的第一行。
  • ::first-letter 匹配元素的第一个字母。
  • ::selection 匹配文档中被用户高亮部分(比如使用鼠标或其他选择设备选中)。

(codepen链接:https://codepen.io/dgwyer/embed/xjBBqN)

::first-line::first-letter 仅在应用于块级元素时才起作用。另外要小心应只在特定元素上使用 ::first-letter,否则每个段落都会有一个首字母下沉,这可能不是你想要的!

还有一些内容选择器还未得到广泛支持,但是当它们得到支持时,它们将开启各种可能性。

以下是需要我们关注的一些内容选择器:

  • ::inactive-selection 匹配当前窗口处于非激活状态下已被选取的文档中被用户高亮部分。
  • ::spelling-error 匹配浏览器标识拼写错误的文本段。
  • ::grammar-error 匹配浏览器标识语法错误的文本段。
  • ::marker 匹配列表项目标记符号(即 <li> 元素由 type 属性生成出的标记符号)。
  • ::placeholder 匹配表单元素中的占位符文本。

杂项选择器

我们再拿出点时间了解一下那些不属于任何类别的选择器,这其中有部分是实验性的,所以你必须等待一段时间才能在生产中使用。

:target 选择器匹配的是一个ID元素,其ID与当前URL片段相对应。例如我们有一个 id="part1" 的元素,当前页面URL是:

https://mysite.com#part1

这时我们就可以匹配到 id="part1" 这个元素并做如下等设置:

:target { border: 1px red solid; }

如果当你遇到一个复杂的选择器组合时,或许 :matches() 选择器可以帮到你。例如你有以下的选择器组合:

nav p.content,
header p.content,
main p.content,
sidebar p.content,
footer p.content {
  margin: 15px;
  padding: 10px;
}

我们可以通过 :matches() 选择器进行简化处理:

:matches(nav, header, main, sidebar, footer) p:content {
  margin: 15px;
  padding: 10px;
}

太好了! 这将有助于使样式表更具可读性。

接下来的 :any-link 选择器,它可以同时匹配 :link:visited 两种链接状态。

下面两段代码,我们会得到相同的效果:

:any-link {
  color: red;
}
:link, :visited {
  color: red;
}

我们最后再介绍一组选择器:

  • :dir() 匹配 dir 属性定义了文本方向的元素。
  • :lang() 匹配 lang 属性定义了语言的元素。

这两个选择器都与站点的语种有关联。

:dir() 接受参数 ltr (从左到右) 或 rtl (从右到左),具体取决于您要匹配的文本方向,目前仅Firefox支持。

:dir(rtl) 匹配是定义了从右到左文本方向的元素。

lang 属性可以给每个元素做单独的语言设置。

<div lang=”en”>The language of this element is set to English.</div>
<div lang=”el”>Η γλώσσα αυτού του στοιχείου έχει οριστεί στα ελληνικά.</div>
<div lang=”is”>Tungumál þessa þáttar er sett á íslensku.</div>

我们将含义相同的三种语言文字分别放到各自的 <div> 中,并用 lang 属性分别单独给其定义对应的语言代码。

  • en — English language(英语)
  • el — Greek language(希腊语)
  • is — Icelandic language(冰岛语)

现在就可以通过 :lang 选择器来匹配定义了不同语言的 <div> 元素:

:lang(en) { color: red; }
:lang(el) { color: green; }
:lang(is) { color: blue; }

下面是演示实例:

(codepen链接:https://codepen.io/dgwyer/embed/xjBoNG)

好消息是所有主流浏览器都支持 :lang() 选择器。

资源

如果你要查询一个选择器,或者需要深入研究CSS规范,那么你可以参看以下的资源:

  • MDN Web Docs (https://developer.mozilla.org/zh-CN/)
  • CSS Specifications (https://www.w3.org/Style/CSS/specs.en.html)
  • Can I Use (https://caniuse.com)

结语

我希望这篇文章对你有用,我也会继续探索CSS选择器技巧的各种可能性。

使用纯CSS可以做很多很酷的事情,这在几年前是不可能实现的。

非常炫目的效果和动画现在都可以纯CSS实现,不用任何的JavaScript,这真的让人感到兴奋。