高级 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;
}
这将产生以下内容:
应用交替背景颜色
使用 的函数符号,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;
}
这将选择从第一个元素开始的每第三个元素:
本质上,这+ [number]
会改变起始索引。
为了完成我们的图案,我们定义以下规则,将添加的数字递增为重复图案中颜色的顺序:
li:nth-child(3n + 2) {
background-color: darkcyan;
}
li:nth-child(3n + 3) {
background-color: lightskyblue;
}
产生以下完成的结果:
要获得扩展指南,请nth-child
查看CSS-Tricks 中的配方参考和nth-child 测试器来探索如何构建这些选择器。
喜欢本指南并找到一些实用的解决方案?我想喝杯咖啡,激励我创作更多资源!我还提供前端评审和指导课程,请选择一个选项来支持我。
删除子元素的额外间距
如果您没有使用以零边距开始所有元素的重置,则可能会遇到排版元素创建额外的不需要的边距,从而导致视觉容器内的间距不平衡。
伪类并不总是需要直接附加到元素上,这意味着我们可以执行以下规则,该规则附加到恰好是任何父级的最后一个子级的任何margin-bottom
元素上,并确保它没有:
:last-child {
margin-bottom: 0;
}
从选择器中排除元素
谨慎应用: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;
}
您还可以链接:not()
选择器,因此也许您想为表单字段输入创建规则,但不针对某些类型:
input:not([type="hidden"]):not([type="radio"]):not([type="checkbox"])
还可以包括其他伪选择器,:not()
例如排除:disabled
按钮的状态:
button:not(:disabled)
button
通过首先定义样式重置,您可以获得更整洁的规则,然后仅将颜色样式、边框等应用于非禁用按钮,而不是稍后删除这些样式button:disabled
。
高效选择元素组
新支持的 :is()
伪类:
“...以选择器列表作为参数,并选择列表中任何一个选择器能够选择的元素。” - MDN 文档
:is()
可以产生重大影响的一种方法是更紧凑地选择排版元素,例如:
:is(h1, h2, h3, h4)
或者更简洁地限定布局样式,例如:
:is(header, main, footer)
我们甚至可以结合:is()
并:not()
真正精简我们的选择器,在这种情况下选择非标题的元素:
:not(:is(h1,h2,h3,h4))
要查看此选择器的具体内容,请查看ModernCSS 配套项目 SmolCSS.dev 中的Smol Composable Card Component 。
近期内,webkit
如果您想开始使用此选择器,至少需要包含前缀版本。由于浏览器使用选择器的方式存在一些特殊性,您需要将此规则设置为与 分开的唯一规则,is()
以避免浏览器同时丢弃这两条规则。
:-webkit-any(header, main, footer)
为当前锚链接元素设置样式
当元素是锚链接(文档片段标识符)的目标时https://url.com/#anchor-here
- 您可以使用来设置它的样式:target
。
我的项目 11ty.Rocks 依靠锚链接,例如在访问此链接时可以看到CSS Houdini Worklet Generator。
伪:target
类应该放置在包含该属性的元素上id
。但是,你可以将它与后代选择器链接起来,以影响嵌套元素——也许你想赋予article:target h2
更大的尺寸或类似的东西。
利用:target
伪元素,我添加了一条额外的消息,::before
以帮助向访问者指出他们提供了哪个项目的链接,如下所示(“您正在寻找我......”)
额外提示:使用 (或您选择的其他值)确保在滚动时元素顶部之前留出一些间距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>
默认样式(未访问)添加了伪元素,并使其颜色与页面背景相同,以在视觉上隐藏它:
a span[aria-hidden]::after {
content: "✔";
color: var(--color-background);
}
然后,当链接被访问时,我们更新颜色以使其可见:
a:visited span[aria-hidden]::after {
color: var(--color-primary);
}
高级交互:focus-within
新兴的伪类具有:focus-within
可用的 polyfill,但除此之外应谨慎使用或作为渐进增强。
:focus-within
MDN 文档中描述的伪类:
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);
}
以下是如何id
class
使用相同思路在伪元素中显示元素和值的要点。您也可以分享此技巧的推文 >
强调文章开头
“lede”(发音为“lead”)是新闻纸术语,指新闻文章的第一段,旨在总结文章的关键点(您可能听过“不要埋没 lede!”这句话)。
我们可以将 的伪类:first-of-type
与 的伪元素结合起来,:first-line
以强调段落文案的第一行。有趣的是,这是动态的,会随着视口大小的变化而变化。
article p:first-of-type:first-line {
font-weight: bold;
font-size: 1.1em;
color: darkcyan;
}
产生以下固有响应结果:
确保文本选择的对比度可访问
尽管我们许多人每天都会进行多次的互动,但经常被忽略的风格是文本选择。
当浏览器尝试处理此事件的样式时,可能会丢失对比度。我在为ModernCSS.dev进行样式设置时就遇到了这个问题,因为使用了较暗的主题。
为了解决这个问题,我们可以使用::selection
伪元素来提供自定义文本颜色和背景颜色:
::selection {
background: yellow;
color: black;
}
自定义列表项目符号样式
一个专门用于设置列表项目符号样式的新兴伪元素是::marker
。
有关浏览器支持链接及其使用方法的示例,请查看我的教程“完全自定义列表样式”中的部分。
在 ModernCSS.dev 上发现更多伪元素的用途
通过浏览ModernCSS.dev,你还能找到多少其他示例?我很乐意听到你的发现、你的收获以及任何其他反馈!欢迎在 Twitter 上联系我,或者@5t3ph
在分享本文或 ModernCSS.dev 上的其他文章时给我留言!
其他资源
- MDN 文档中的 CSS 选择器
- 选择器解释- 输入任意选择器来了解受影响的内容
- Polypane 的 CSS 特异性计算器- 发现选择器特异性的级别
- CSS Diner - 一款测试您创建 CSS 选择器能力的游戏
- Style Stage - 我的另一个项目Style Stage是练习新选择器知识的好地方,它是一个由社区贡献的现代 CSS 展示平台。它的一个限制是无法添加新的类或 ID,所以你需要练习你的选择器技能才能成功创建样式表提交!
鏂囩珷鏉ユ簮锛�https://dev.to/5t3ph/guide-to-advanced-css-selectors-part-two-1300回到第一部分,了解其他五类高级 CSS 选择器。如果您从本指南中有所收获,并且能够做到,我将非常感激您送我一杯咖啡,以便我为您带来更多教程和资源!