高级 CSS 选择器指南 - 第二部分

2025-06-08

高级 CSS 选择器指南 - 第二部分

这是系列文章的第 25 集,该系列文章探讨了现代 CSS 解决方案,以解决我过去 13 多年来作为前端开发者遇到的各种问题。访问ModernCSS.dev即可查看整个系列文章及其他资源

延续第一部分,本期将重点介绍高级 CSS 选择器(分为伪类和伪元素)及其实际应用。我们将特别讲解 的语法nth-child

第二部分(本文):

第一部分:


伪类

这是最大的类别,也是最依赖于上下文的类别。

伪类是当与元素的选定状态或上下文匹配时应用的关键字。

这些极大地增强了 CSS 的功能,并实现了过去经常被错误地归于 JavaScript 的功能。

一些选择器是有状态的:

  • :focus
  • :hover
  • :visited
  • :target
  • :checked

而其他的则与元素的顺序有关:

  • :nth-child()/:nth-of-type()
  • :first-child/:first-of-type
  • :last-child/:last-of-type
  • :only-child/:only-of-type

然后是非常有用伪类:not(),新支持的:is(),以及:root随着 CSS 自定义属性(变量)支持率上升而成为焦点的伪类。

查看 MDN 文档以获取可用伪类的完整列表,包括特定于表单输入、video标题和语言的可用选项,以及一些目前正在实施的选项。

伪类的实际应用

斑马条纹表行

这一nth系列选择器的应用非常广泛。您可以使用它们来创建任何您想要以任意重复模式出现的元素,并使用从 1 开始的索引。

表格行上的斑马条纹就是一个很好的例子。

选择nth-child器可以使用整数,也可以使用函数符号even或的关键字来定义odd。我们将使用关键字来最有效地生成斑马条纹规则:

tbody tr:nth-child(odd) {
  background-color: #ddd;
}
Enter fullscreen mode Exit fullscreen mode

这将产生以下内容:

一个两列表格,其中表体中的每行(奇数行)的背景均为浅灰色

应用交替背景颜色

使用 的函数符号,nth-child我们可以交替显示一系列背景颜色,并确保无论元素数量多少,图案都会按照定义的顺序重复。因此rebeccapurple, 、darkcyan、的图案lightskyblue将按照该顺序重复。

它的工作方式是定义颜色总数 - 3- 与 并列n,表示从 0 开始的所有正数,并将乘以关联的数字,在本例中为3。因此,单独使用3n会选择第 3 个项目、第 6 个项目、第 9 个项目,依此类推。它不会选择列表中的第一个,因为3 x 0 = 0

对于我们的重复模式,我们希望选择的第一个项目是调色板中的第一个颜色。

因此,我们将符号扩展为3n + (integer corresponding to color order),因此我们的第一个颜色规则变成:

li:nth-child(3n + 1) {
  background-color: rebeccapurple;
}
Enter fullscreen mode Exit fullscreen mode

这将选择从第一个元素开始的每第三个元素:

5 个堆叠项目,其中第一个和第四个应用了背景颜色:rebeccapurple

本质上,这+ [number]会改变起始索引。

为了完成我们的图案,我们定义以下规则,将添加的数字递增为重复图案中颜色的顺序:

li:nth-child(3n + 2) {
  background-color: darkcyan;
}

li:nth-child(3n + 3) {
  background-color: lightskyblue;
}
Enter fullscreen mode Exit fullscreen mode

产生以下完成的结果:

要获得扩展指南,请nth-child查看CSS-Tricks 中的配方参考和nth-child 测试器来探索如何构建这些选择器。

喜欢本指南并找到一些实用的解决方案?我想喝杯咖啡,激励我创作更多资源!我还提供前端评审和指导课程,请选择一个选项来支持我

删除子元素的额外间距

如果您没有使用以零边距开始所有元素的重置,则可能会遇到排版元素创建额外的不需要的边距,从而导致视觉容器内的间距不平衡。

伪类并不总是需要直接附加到元素上,这意味着我们可以执行以下规则,该规则附加到恰好是任何父级的最后一个子级的任何margin-bottom元素上,并确保它没有:

:last-child {
  margin-bottom: 0;
}
Enter fullscreen mode Exit fullscreen mode

从选择器中排除元素

谨慎应用:not()对于排除被选择的元素非常有用。

:not()我们探讨了属性选择器部分中的几种用途,特别是a:not([class])针对未应用其他类的定位链接。

:not()非常适合用于实用程序框架或设计系统,以增加可能应用于任何事物且在某些组合上存在已知问题的类的特殊性。

对于带有链接的类,将其排除的一个扩展示例是,当您调整文本的对比度(可能在暗模式上下文中)时,并且希望将对比度调整也应用于文本链接:

/* Non dark mode application */
a:not([class]) {
  color: blue;
}

/* Update text color for dark mode */
.dark-mode {
  color: #fff;
}

/* Extend the color update to links via `inherit` */
.dark-mode a:not([class]) {
  color: inherit;
}

Enter fullscreen mode Exit fullscreen mode

您还可以链接:not()选择器,因此也许您想为表单字段输入创建规则,但不针对某些类型:

input:not([type="hidden"]):not([type="radio"]):not([type="checkbox"])
Enter fullscreen mode Exit fullscreen mode

还可以包括其他伪选择器,:not()例如排除:disabled按钮的状态:

button:not(:disabled)
Enter fullscreen mode Exit fullscreen mode

button通过首先定义样式重置,您可以获得更整洁的规则,然后将颜色样式、边框等应用于非禁用按钮,而不是稍后删除这些样式button:disabled

高效选择元素组

支持的 :is()伪类:

“...以选择器列表作为参数,并选择列表中任何一个选择器能够选择的元素。” - MDN 文档:is()

可以产生重大影响的一种方法是更紧凑地选择排版元素,例如:

:is(h1, h2, h3, h4)
Enter fullscreen mode Exit fullscreen mode

或者更简洁地限定布局样式,例如:

:is(header, main, footer)
Enter fullscreen mode Exit fullscreen mode

我们甚至可以结合:is():not()真正精简我们的选择器,在这种情况下选择非标题的元素:

:not(:is(h1,h2,h3,h4))
Enter fullscreen mode Exit fullscreen mode

要查看此选择器的具体内容,请查看ModernCSS 配套项目 SmolCSS.dev 中的Smol Composable Card Component 。

近期内,webkit如果您想开始使用此选择器,至少需要包含前缀版本。由于浏览器使用选择器的方式存在一些特殊性,您需要将此规则设置为与 分开的唯一规则,is()以避免浏览器同时丢弃这两条规则。

:-webkit-any(header, main, footer)
Enter fullscreen mode Exit fullscreen mode

为当前锚链接元素设置样式

当元素是锚链接(文档片段标识符)的目标时https://url.com/#anchor-here- 您可以使用来设置它的样式:target

我的项目 11ty.Rocks 依靠锚链接,例如在访问此链接时可以看到CSS Houdini Worklet Generator

:target类应该放置在包含该属性的元素上id。但是,你可以将它与后代选择器链接起来,以影响嵌套元素——也许你想赋予article:target h2更大的尺寸或类似的东西。

利用:target伪元素,我添加了一条额外的消息,::before以帮助向访问者指出他们提供了哪个项目的链接,如下所示(“您正在寻找我......”)

:target 样式应用于 11ty.Rocks 上的一篇文章,其中包含此图像之前描述的消息

额外提示:使用 (或您选择的其他值)确保在滚动时元素顶部之前留出一些间距scroll-margin-top: 2em;。这应被视为渐进式增强,请务必检查浏览器对 的支持情况scroll-margin-top

直观地显示已访问的存档链接

:visited类非常特殊,因为它有可能被利用来侵犯用户隐私。为了解决这个问题,浏览器制造商限制了允许使用 的 CSS 样式:visited

Una Kravets 有一个更深入的参考资料,探讨如何创建有用的:visited样式,但这里是我为 Style Stage 的访问者使用的简化版本,以跟踪他们已经查看过的样式

一个关键的问题是,通过应用的样式:visited将始终使用父级的 alpha 通道 - 这意味着,您不能使用它rgba从不可见变为可见,您必须更改整个颜色值。

因此,要隐藏初始状态,您需要能够使用纯色,例如页面背景颜色。

此外,出于可访问性考虑,如果伪元素内容是图标或表情符号,则可能不希望读取它,因为我们无法为content值提供可访问的名称。辅助技术在是否读取伪元素内容方面存在不一致,因此我们可以尝试使用 来确保它被忽略aria-hidden="true"

我们的第一步是在链接中添加一个跨度,这就是我们最终将:visited样式应用到的内容:

<a href="#">Article Title <span aria-hidden="true"></span></a>
Enter fullscreen mode Exit fullscreen mode

默认样式(未访问)添加了伪元素,并使其颜色与页面背景相同,以在视觉上隐藏它:

a span[aria-hidden]::after {
  content: "✔";
  color: var(--color-background); 
}
Enter fullscreen mode Exit fullscreen mode

然后,当链接被访问时,我们更新颜色以使其可见:

a:visited span[aria-hidden]::after {
  color: var(--color-primary); 
}
Enter fullscreen mode Exit fullscreen mode

高级交互:focus-within

新兴的伪类具有:focus-within可用的 polyfill,但除此之外应谨慎使用或作为渐进增强。

:focus-withinMDN 文档中描述的伪

CSS:focus-within伪类表示一个元素获得了焦点,或者包含一个获得了焦点的元素。换句话说,它表示一个元素本身与:focus伪类匹配,或者有一个后代与 伪类匹配:focus

要了解实际使用方法,请查看仅 CSS 可访问下拉导航菜单:focus-within的教程

伪元素

伪元素允许你为所选元素的特定部分添加样式。它们在实际应用中用途广泛,目前支持程度最高的有以下几种:

  • ::after
  • ::before
  • ::first-letter
  • ::first-line
  • ::selection

伪元素的实际应用

额外的视觉元素带来造型优势

伪元素会创建一个额外的元素,该元素在视觉上看起来像是 DOM 的一部分,但实际上并非真正的 HTML DOM 的一部分。它们与任何真正的 DOM 元素一样,可以完全自定义样式::before::after

我把这些元素用于各种装饰。由于它们的行为与真实元素类似,因此在使用弹性框或 CSS 网格布局时,它们会被计算为子元素,这大大增强了它们在我的工具箱中的功能。

::before使用和的几个关键概念::after

  • 需要该content属性才能显示,但该属性可以设置为空字符串 -content: "";
  • 关键文本内容不应包含在content值中,因为辅助技术无法一致地访问它
  • 除非另有定位,::before否则将显示在主要元素内容之前,::after并将显示在主要元素内容之后。

以下是仅应用了一点样式的默认行为的演示:

一小段文字显示了

请注意,它们默认表现得像内联元素,并且对于较长的内容也遵循换行行为:

稍长一些的段落,带有换行符,显示文本

以下是添加display: flex到该段落的单项调整:

相同的多行段落,但

将其替换为display: grid

相同的多行段落,但

和元素可以快速添加简单、一致的排版效果::before::after其中一些可以在 CodePen 演示中看到:

你掌握了表情符号中的诀窍了吗?

content我们可以通过以下函数检索元素上任何属性的值以在属性中使用attr()

/*
<h2 class="emoji" data-emoji="😍">
*/
.emoji::before {
  content: attr(data-emoji);
}
Enter fullscreen mode Exit fullscreen mode

以下是如何idclass使用相同思路在伪元素中显示元素值的要点。您也可以分享此技巧的推文 >

强调文章开头

“lede”(发音为“lead”)是新闻纸术语,指新闻文章的第一段,旨在总结文章的关键点(您可能听过“不要埋没 lede!”这句话)。

我们可以将 的伪类:first-of-type与 的伪元素结合起来,:first-line以强调段落文案的第一行。有趣的是,这是动态的,会随着视口大小的变化而变化。

article p:first-of-type:first-line {
  font-weight: bold;
  font-size: 1.1em;
  color: darkcyan;
}
Enter fullscreen mode Exit fullscreen mode

产生以下固有响应结果:

应用前面描述的规则后,调整视口大小的 gif 演示,可以看到随着段落第一行的字数变化,样式仍然只影响第一行

确保文本选择的对比度可访问

尽管我们许多人每天都会进行多次的互动,但经常被忽略的风格是文本选择。

当浏览器尝试处理此事件的样式时,可能会丢失对比度。我在为ModernCSS.dev进行样式设置时就遇到了这个问题,因为使用了较暗的主题。

为了解决这个问题,我们可以使用::selection伪元素来提供自定义文本颜色和背景颜色:

::selection {
  background: yellow;
  color: black;
}
Enter fullscreen mode Exit fullscreen mode

自定义列表项目符号样式

一个专门用于设置列表项目符号样式的新兴伪元素是::marker

有关浏览器支持链接及其使用方法的示例,请查看我的教程“完全自定义列表样式”中的部分。

在 ModernCSS.dev 上发现更多伪元素的用途

通过浏览ModernCSS.dev,你还能找到多少其他示例?我很乐意听到你的发现、你的收获以及任何其他反馈!欢迎在 Twitter 上联系我,或者@5t3ph在分享本文或 ModernCSS.dev 上的其他文章时给我留言!

其他资源

回到第一部分,了解其他五类高级 CSS 选择器。如果您从本指南中有所收获,并且能够做到,我将非常感激您送我一杯咖啡,以便我为您带来更多教程和资源!

鏂囩珷鏉ユ簮锛�https://dev.to/5t3ph/guide-to-advanced-css-selectors-part-two-1300
PREV
我如何在 17 小时内构建并发布一个小型 Web 应用
NEXT
使用 a11y-color-tokens 生成可访问的 UI 颜色