了解伪类选择器

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

伪类选择器是在 CSS 选择器前加上冒号的选择器。您可能对其中的一些非常熟悉,例如 hover。

a:hover {
  /* Yep, hover is a pseudo class */
}

它们在各种情况下都非常有用。有些是 CSS3,有些是 CSS2……这取决于每个特定的选择器。在 IE 之外,它们具有良好的浏览器支持。在 IE 中,即使是 IE8,支持也相当匮乏。但是,IE9 预览版完全支持它们。与链接相关的选择器可以工作,但其他功能很少。让我们简要了解一下每个选择器。不用担心,数量并不多。

:link – 也许是最容易引起混淆的与链接相关的伪选择器。难道所有的 <a> 都是链接吗?如果没有 href 属性,则不是。这仅选择具有 href 属性的链接,因此与 a[href] 本质上相同。如果 任意元素链接 成为现实,此选择器将变得更有用。

:visited – 选择当前浏览器已访问过的链接。

:hover – 当鼠标光标移到链接上时,该链接处于悬停状态,这将选择它。

:active – 在激活链接(点击或以其他方式激活)时选择它。例如,对于按钮样式链接的“按下”状态或使所有链接更像按钮

有一种有趣的技巧可以记住所有链接伪类选择器。查看每个选择器的第一个字母:LVHA … LOVE HATE

:focus – 为链接定义悬停样式很棒,但这对那些使用键盘导航到达链接的用户没有帮助。:focus 将选择当前键盘焦点所在的链接。这不仅限于链接,还可以(实际上应该)用于输入和文本区域。 有些人会告诉你为任何具有 :hover 样式的元素定义 :focus 样式。

Form with a text input in focus. Yellow background is a focus style.
表单中带有焦点的文本输入。黄色背景是焦点样式。

:target – 目标伪类与 ID 结合使用,并在当前 URL 中的哈希标签与该 ID 匹配时匹配。因此,如果您位于 URL www.yoursite.com/#home,则选择器#home:target将匹配。这可能非常强大。例如,您可以创建一个选项卡区域,其中选项卡链接到哈希标签,然后面板通过匹配 :target 选择器(例如)并使用 z-index 移动到顶部来“激活”。

:enabled – 选择处于启用默认状态并准备使用的输入。

:disabled – 选择具有disabled属性的输入。许多浏览器会使输入变成淡灰色的,您可以使用此选择器控制它。

使用 :disabled 属性的表单。

:checked – 选择已选中的复选框。

:indeterminate – 选择处于既未选中也未取消选中状态的单选按钮(例如,当页面加载带有单选按钮选项但未设置默认值时)。

处于“炼狱”状态的单选按钮集。或者更准确地说,处于它们的 :indeterminate 状态。

:required – 选择具有 required 属性的输入。
:optional – 选择没有 required 属性的输入。

:read-only / :read-write – 根据 readonlydisabled 属性的组合选择元素。

基于位置/编号的伪类选择器

:root – 选择文档根元素。几乎肯定会选择 元素,除非您是在某种奇怪的环境中工作,该环境也允许使用 CSS。也许是 XML。

:first-child – 选择父元素中的第一个元素。

:last-child – 选择父元素中的最后一个元素。

:nth-child() – 根据提供的简单代数表达式(例如“2n”或“4n-1”)选择元素。能够执行诸如选择偶数/奇数元素、“每三个”、“前五个”等操作。在此处详细介绍,并提供了一个测试工具

:nth-of-type() – 与 :nth-child 类似,但用于同一级别元素类型不同的情况。例如,如果在一个 div 内有若干段落和若干图像,并且您想选择所有奇数图像。:nth-child 在这里不起作用,您将使用 div img:nth-of-type(odd)。在处理定义列表及其交替的 <dt> 和 <dd> 元素时特别有用。

:first-of-type – 选择任何父元素中此类型的第一个元素。因此,如果您有两个 div,每个 div 中都包含一个段落、图像、段落、图像。那么div img:first-of-type将选择第一个 div 中的第一个图像和第二个 div 中的第一个图像。

:last-of-type – 与上面相同,只是会选择第一个 div 中的最后一个图像和第二个 div 中的最后一个图像。

:nth-last-of-type() – 与 :nth-of-type 类似,但它从底部向上计数而不是从顶部向上计数。

:nth-last-child() – 与 :nth-child 类似,但它从底部向上计数而不是从顶部向上计数。

:only-of-type – 仅当元素是当前父元素中唯一的同类元素时才选择它。

基于位置/编号的伪类选择器

关系伪类选择器

:not() – 从现有匹配集中删除与 :not() 参数内选择器匹配的元素。例如,所有 div 除了那些具有“music”类的 div =div:not(.music)。规范指出 :not 选择器不能嵌套,但可以链接。某些浏览器(Firefox)也支持将逗号分隔的选择器作为选择器参数,尽管链接它们会是一个更安全的选择。也与属性选择器结合使用,例如input:not([disabled]).

:empty – 选择不包含任何文本和子元素的元素。例如:

::first-letter – 选择元素中文本的第一个字母。典型用法:首字母大写。

::first-line – 选择元素中文本的第一行。典型用法:将第一个句子设置为小型大写字母,作为排版吸引眼球/引导。

:lang – 此伪选择器位于 CSS3 规范中,但仅在 IE 8+ 中实现。将匹配任何具有或为具有匹配 lang 属性的元素的后代的元素。例如,:lang(fr) 将匹配任何段落,即使没有 lang 属性,如果父 body 具有 lang="fr" 作为属性。

快速说明

您可以像链接类和 ID 选择器一样链接伪选择器。在我们查看 :first-letter:first-line 时,这尤其有用。您可能不想对页面上的每个段落都使用首字母大写,而只想对第一个段落使用,因此,p:first-child:first-letter { }

使用 :first-letter 进行首字母大写,它会增大字体大小并向左浮动。

::before – 能够在特定元素之前添加内容。例如,在块引用之前添加一个引号,或者在特定段落之前添加一个图像以将其与其他内容区分开来。

::after – 能够在特定元素之后添加内容。例如,在块引用之后添加一个结束引号。它也常用于 clearfix,在元素之后添加一个空空间来清除浮动,而无需任何额外的 HTML 标记。

伪元素与伪类

上面这两个选择器被恰当地称为伪“元素”(而不是选择器),因为它们不选择页面上存在的任何“真实”元素。这同样适用于这两个选择器,以及前面部分的 ::first-letter::first-line。明白了吗?就像 ::first-letter 选择的第一个字母本身并不是一个元素,它只是现有元素的一部分,因此,是伪元素。

选择器样式名称作用特异性
::元素选择/创建一些实际的内容0 0 0 1
:在特定条件下选择元素0 0 1 0

标签限定

这些选择器可以进行标签限定,这意味着它们只有在同时满足元素(标签)和选择器匹配时才会应用。例如

p:first-child {
  color: red;
}

只有当另一个元素的第一个子元素是 <p>时,它才会匹配。如果不是,则不会匹配。

已弃用

:contains() – 据我所知,这个选择器已经消失了。当前的 CSS3 规范已将其移除。我不知道具体原因,如果你知道的话,请告诉我。乍一看,它看起来非常有用(能够根据包含的文本内容选择对象)。这可能是因为存在一些问题,或者在选择器中包含内容是不希望的。我更希望它通过元素而不是文本进行选择,例如 p:contains(img),但可惜,没有这样的运气。

更新:现在有了 a :has() 选择器

::selection – 允许更改选中文本的样式。它最初是在 CSS 选择器级别 3 中起草的,但在达到推荐状态之前被移除。尽管如此,它在一些浏览器中得到了实现,这些浏览器可能会保留对它的实验性支持。对于 Firefox,您可以使用 ::-moz-selection。 更多信息请点击此处

更新:::selection 现在完全成为标准了,可以放心地使用它!

jQuery 使用

jQuery 可以在其选择器中使用所有这些,这很棒。更棒的是,jQuery 还提供了其他可用的伪类选择器。

:first – 匹配已匹配集合中的第一个实例。这与 :nth-child(1) 不同,后者只有在选择器匹配并且它是第一个子元素时才会选择。对于 :first,选择器匹配后,它会找到第一个匹配项,而不管子元素的位置。

:eq()jQuery 的选择器引擎不支持 :nth-of-type,但这非常相似。现在 支持了它从已匹配的集合中选择第 X 个元素。它也是从 0 开始索引(0 是第一个元素),这与 :nth-child 不同,后者第一个元素是 1。

:contains('text') – 这个选择器在 CSS 中已被移除,但在 jQuery 中仍然有效。

:lt() – 与 :nth-child(-n+X) 相同,即选择“前 X 个元素”。

:gt() – 与 :nth-child(n+X) 相同,即选择除“前 (X-1) 个元素”之外的所有元素。

:even – 与 :nth-child(even):nth-child(2n) 相同。

:odd – 与 :nth-child(odd):nth-child(2n+1) 相同。

:has() – 在匹配之前测试元素是否具有某个选择器的后代,例如 :has("div.intro")

实际上还有很多其他的 jQuery 选择器,它们都非常巧妙且有用(或者至少提高了可读性)。请查看 选择器文档 以了解更多信息。

jQuery 无法真正帮助你处理像 ::before::after 这样的伪元素,但你可以在 某些浏览器中访问它们的值。例如,如果一个 div 有一些 ::before 生成的内容,你可以像这样获取它的值:

var div = document.querySelector("div");

var content = window
  .getComputedStyle(div, '::before')
  .getPropertyValue('content');

特异性

类选择器和伪类选择器具有相同特异性权重。伪元素具有元素选择器的特异性。

li             {} /* specificity = 0,0,0,1 */
li:first-child {} /* specificity = 0,0,1,1 */
li:first-line  {} /* specificity = 0,0,0,2 */
li.red         {} /* specificity = 0,0,1,1 */

通常,它们在 CSS 中以组合方式使用或在后面列出,因此希望不会造成太多问题……

ul li.friend { margin: 0 0 5px 0; }
ul li:last-child { margin: 0; }

在这种情况下,边距归零将起作用(假设它匹配相同的元素),但这仅仅是因为边距归零在后面列出(它们具有相同特异性)。所以……要注意这一点。