概述
CSS 在许多方面都很出色,但在两方面特别出色:**选择元素**和**为其设置样式**。这就是 CSS 的存在理由,也是它成为核心 Web 语言的原因。在本指南中,我们将介绍选择元素的不同方法,因为我们编写的样式在没有选择要应用样式的元素的能力的情况下几乎毫无用处。
关于 **CSS 选择器** 的真实来源在 Selectors 模块 4 级 规范中进行了说明。除了一个例外(我们稍后会讲到),这里介绍的所有选择器都被各种浏览器广泛支持,当然也包括所有现代浏览器。
除了选择器之外,本指南还介绍了 **CSS 组合器**。如果选择器识别我们所选的内容,您可能会认为组合器是如何应用样式的。组合器就像我们给 CSS 的额外指令,用于选择页面上的一个非常特定的元素,这与我们在搜索引擎中使用过滤器来查找我们想要的精确结果的方式非常相似。
快速参考
常用选择器
/* Universal */
* {
box-sizing: border-box;
}
/* Type or Tag */
p {
margin-block: 1.5rem;
}
/* Classname */
.class {
text-decoration: underline;
}
/* ID */
#id {
font-family: monospace;
}
/* Relational */
li:has(a) {
display: flex;
}
常用组合器
/* Descendant */
header h1 {
/* Selects all Heading 1 elements in a Header element. */
}
/* Child */
header > h1 {
/* Selects all Heading 1 elements that are children of Header elements. */
}
/* General sibling */
h1 ~ p {
/* Selects a Paragraph as long as it follows a Heading 1. */
}
/* Adjacent sibling */
h1 + p {
/* Selects a Paragraph if it immediately follows a Heading 1 */
}
/* Chained */
h1, p {
/* Selects both elements. */
}
通用选择器
当我们谈论 **CSS 选择器** 时,我们指的是 CSS 规则集的第一部分
/* CSS Ruleset */
selector {
/* Style rule */
property: value;
}
看到那个 selector
吗?它可以像我们要选择的 HTML 标签一样简单。例如,让我们选择给定页面上的所有 <article>
元素。
/* Select all <article> elements... */
article {
/* ... and apply this background-color on them */
background-color: hsl(25 100% 50%);
}
这就是选择元素以应用样式的一般过程。根据 HTML 标签选择元素仅仅是几种 **选择器类型** 中的一种。让我们在下一节看看它们是什么。
元素选择器
元素选择器正是我们在上一个示例中看到的选择器类型:选择元素的 HTML 标签并开始设置样式!
这很好,但请考虑:您是否真的想选择页面上的所有 <article>
元素?当我们通过其标签选择元素时,就是我们正在做的事情——任何与该标签匹配的 HTML 元素都会获得样式。以下演示选择页面上的所有 <article>
元素,然后为它们应用白色 (#fff
) 背景。请注意,尽管我们只编写了一个选择器,但所有三个文章都获得了白色背景。
我尝试使本指南中此演示和其他演示的相关代码在 CSS 选项卡的顶部提供。@layer
中的任何内容都可以忽略。如果您不熟悉 @layer
,您可以在我们的 CSS 级联层指南 中了解更多信息。
但是也许我们真正想要的是让第一个元素具有不同的背景——也许它是一个特色内容,我们需要让它从其他文章中脱颖而出。这要求我们对用于应用样式的选择器类型更具体。
让我们将注意力转向其他允许我们更具体地选择我们要选择的内容的选择器类型。
ID 选择器
**ID 选择器** 是我们可以选择一个元素而不会选择另一个相同元素类型的方法之一。假设我们要更新我们 <article>
示例中的 HTML,以便第一个文章用 ID “标记”
<article id="featured">
<!-- Article 1 -->
</article>
<article>
<!-- Article 2 -->
</article>
<article>
<!-- Article 3 -->
</article>
现在,我们可以使用该 ID 将第一个文章与其他文章区分开来,并专门为其应用样式。在编写 CSS 选择器时,我们在 ID 名称前面加上井号字符 (#
) 以正确选择它。
/* Selects all <article> elements */
article {
background: #fff;
}
/* Selects any element with id="featured" */
#featured {
background: hsl(35 100% 90%);
border-color: hsl(35 100% 50%);
}
好了,这使得第一个文章比其他文章更突出!
在你到处添加 ID 到你的 HTML 之前,**请注意 ID 被认为是一种选择元素的笨重方法。** ID 非常具体,以至于很难用 CSS 中的其他样式覆盖它们。ID 比试图覆盖它的任何选择器都具有更高的特异性,因此任何想要覆盖它的选择器都需要至少一个 ID。当您接近此特异性战争阶梯的顶端时,它往往会导致使用 !important
规则等,而这些规则反过来又几乎不可能被覆盖。
让我们重新排列上一个示例中的 CSS,以查看它的实际效果
/* Selects any element with id="featured" */
#featured {
background: hsl(35 100% 90%);
border-color: hsl(35 100% 50%);
}
/* Selects all <article> elements */
article {
background: #fff;
}
ID 选择器现在位于元素选择器之前。根据 CSS 级联如何确定样式,您可能期望所有文章元素都获得白色背景,因为该规则集位于 ID 选择器规则集之后。但事实并非如此。
因此,您看到了 ID 在选择元素时可能会过于“具体”,因为它会影响 CSS 级联应用样式的顺序,从而使样式更难管理和维护。
避免将 ID 作为选择器的另一个原因是:我们技术上只允许在页面上 使用一次 ID,每个 ID 仅限一次。换句话说,我们可以用 #featured
设置一个元素,但不能设置两个。如果我们需要将这些样式扩展到其他元素,这会严重限制我们能够设置的样式——甚至还没有考虑覆盖 ID 样式的难度。
ID 的一个更好的用例是在 JavaScript 中选择项目——这不仅可以防止我们在上面看到的样式冲突,还可以帮助维护样式选择和 JavaScript 交互选择之间的关注点分离。
关于 ID 选择器的另一件事:ID 建立了我们所说的“锚点”,这是一个花哨的术语,意思是 **我们可以直接链接到页面上的元素**。例如,如果我们有一个分配了 ID 的文章
<article id="featured">...</article>
…那么我们可以像这样创建一个链接到它的链接
<a href="featured">Jump to article below ⬇️</a>
<!-- muuuuuuch further down the page. -->
<article id="featured">...</article>
单击链接将导航到该元素,就好像该链接是锚定到该元素一样。尝试在以下演示中执行此操作
当我们加入一些 CSS 时,这个小小的 HTML 好东西会开启一些非常有趣的可能性。以下是一些文章来探索这些可能性。
类选择器
**类选择器** 可能是您在 Web 上最常看到的 CSS 选择器类型。类很理想,因为它们比元素选择器更具体,但没有 ID 那么笨重。 您可以阅读 CSS 级联如何确定特异性的深入解释,但以下是一个简化的说明,重点关注我们到目前为止所看到的选择器类型。
这就是类选择器如此受欢迎的原因——它们只比元素稍微更具体,但保持了足够低的特异性,以便在我们需要用另一个规则集中的样式覆盖一个规则集中的样式时可以进行管理。
编写类时唯一的区别是,我们在类名前面加上一个句点 (.
) 而不是井号 (#
)。
/* Selects all <article> elements */
article {
background: #fff;
}
/* Selects any element with class="featured" */
.featured {
background: hsl(35 100% 90%);
border-color: hsl(35 100% 50%);
}
以下是如何在将 #featured
替换为 .featured
时形成我们的 <article>
示例。
相同的结果,更好的特异性。而且,是的,我们绝对可以在同一个元素上组合不同的选择器类型
<article id="someID" class="featured">...</article>
您看到我们有多少种可能性可以选择 <article>
吗?我们可以通过以下方式选择它
- 它的元素类型 (
article
) - 它的 ID (
#someID
) - 它的类 (
.featured
)
以下文章将为您提供一些使用 CSS 类选择器的巧妙想法。
但我们还有更多的方法来选择这样的元素,所以让我们继续。
属性选择器
ID 和类选择器从技术上讲属于这个 **
** 类别。我们称它们为“属性”,因为它们存在于 HTML 中,并提供了有关元素的更多上下文。以下所有内容都是 HTML 中的属性<!-- ID, Class, Data Attribute -->
<article id="#id" class=".class" data-attribute="attribute">
</article>
<!-- href, Title, Target -->
<a href="https://css-tricks.org.cn" title="Visit CSS-Tricks" target="_blank"></a>
<!-- src, Width, Height, Loading -->
<img src="star.svg" width="250" height="250" loading="laxy" >
<!-- Type, ID, Name, Checked -->
<input type="checkbox" id="consent" name="consent" checked />
<!-- Class, Role, Aria Label -->
<div class="buttons" role="tablist" aria-label="Tab Buttons">
在上面的示例代码中,任何带有等号 (=
) 后面跟着值的项都是一个属性。因此,从技术上讲,我们可以使用所有 href
属性等于 https://css-tricks.org.cn
的链接。
a[href="https://css-tricks.org.cn"] {
color: orangered;
}
注意语法?我们使用方括号 ([]
) 来选择属性,而不是像类和 ID 一样使用句点或井号。
属性中使用的等号表明,除了匹配与值完全相等的内容之外,我们还可以做更多的事情来选择元素。确实如此。例如,我们可以确保 href
属性的元素,只要它们不包含大写字母。
/* Case sensitive */
a[href*='css-tricks' s] {}
其中的 s
告诉 CSS 我们只希望选择 href
属性不包含大写字母的链接。
<!-- 👎 No match -->
<a href="https://CSS-Tricks.com">...</a>
<!-- 👍 Match! -->
<a href="https://css-tricks.org.cn">...</a>
如果大小写敏感不是什么大问题,我们也可以告诉 CSS。
/* Case insensitive */
a[href*='css-tricks' i] {}
现在,无论 href
属性中是否有大写字母或小写字母,链接示例中的任一项都将匹配。
<!-- 👍 I match! -->
<a href="https://CSS-Tricks.com">...</a>
<!-- 👍 I match too! -->
<a href="https://css-tricks.org.cn">...</a>
HTML 属性有很多种类型。请务必查看我们的 [data-attribute]
以及它们如何与其他属性相关联,以及 。
通用选择器
CSS-Tricks 与通用选择器有着特殊的关系——它是我们的标志!
没错,星号符号 (*
) 本身就是一个选择器,它的作用是 **选择所有东西**。从字面上看,我们可以选择页面上的所有内容——每个元素——只需使用这个小小的星号。请注意,我说的是每个元素,所以这不会选取像 ID、类甚至伪元素这样的东西。它是用于选择所有元素的元素选择器。
/* Select ALL THE THINGS! 💥 */
* {
/* Styles */
}
或者,我们可以将它与其他选择器类型一起使用,以选择特定元素内部的所有内容。
/* Select everything in an <article> */
article * {
/* Styles */
}
这是一种选择 <article>
中所有内容的便捷方法,即使将来你决定将其他元素添加到 HTML 中的该元素内部也是如此。你最常看到通用选择器使用的情况是在所有元素(包括所有元素和伪元素)上设置 border-sizing
。
*,
*::before,
*::after {
box-sizing: border-box;
}
这段 CSS 代码出现在很多样式表中是有原因的,你可以在以下文章中了解所有相关信息。
有时通用选择器是隐式的。例如,在新的选择器的开头使用伪选择器时。这些选择器选择的是完全相同的内容。
*:has(article) { }
:has(article) { }
伪选择器
伪选择器用于选择伪元素,就像元素选择器用于选择元素一样。伪元素就像元素一样,但它实际上不会出现在 HTML 中。如果伪元素对你来说是新的,我们有一个
可以参考。每个元素都具有一个
伪元素附加到它,即使我们在 HTML 中看不到它。<div class="container">
<!-- ::before psuedo-element here -->
<div>Item</div>
<div>Item</div>
<div>Item</div>
<!-- ::after psuedo-element here -->
</div>
这些非常方便,因为它们是我们连接到元素并应用其他样式的额外方法,而无需在 HTML 中添加更多标记。保持代码尽可能干净,对吧?
我们知道 ::before
和 ::after
是伪元素,因为它们前面是一对冒号 (::
)。我们也是这样选择它们的!
.container::before {
/* Styles */
}
::before
和 ::after
伪元素也可以用单个冒号来写——即 :before
和 :after
——但使用双冒号 ,因为它有助于将伪元素与伪类区分开来。
但是使用伪选择器时有一个问题:**它们需要 content
属性**。这是因为伪元素不是“真实”元素,而是就 HTML 而言不存在的元素。这意味着它们需要可以显示的内容……即使是空内容。
.container::before {
content: "";
}
当然,如果我们在 content
属性中提供文字,这些文字将显示在页面上。
复杂选择器
复杂选择器可能需要一些营销帮助,因为当你开始学习这些东西时,“复杂”是一个非常可怕的词。虽然选择器确实可能变得很复杂而且很混乱,但基本思想非常简单:**我们可以将多个选择器组合到同一个规则集中。**
让我们看看编写这些“不那么复杂”的复杂选择器的三种不同方法。
列出选择器
首先,可以组合选择器,使它们共享同一组样式。我们所做的就是用逗号分隔每个选择器。
.selector-1,
.selector-2,
.selector-3 {
/* We share these styles! 🤗 */
}
你经常会在设置标题样式时看到这一点——它们往往共享相同的通用样式,除了可能 font-size
除外。
h1,
h2,
h3,
h4,
h5,
h6 {
color: hsl(25 80% 15%);
font-family: "Poppins", system-ui;
}
在选择器之间添加换行符可以使代码更易读。你可能可以想象这会变得多么复杂和混乱。例如,下面就是其中一个例子
section h1, section h2, section h3, section h4, section h5, section h6,
article h1, article h2, article h3, article h4, article h5, article h6,
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6,
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
color: #BADA55;
}
嗯,好吧。没有人希望在他们的样式表中出现这种情况。很难看清究竟选择了什么,对吧?
好消息是,我们有现代的方法可以更有效地组合这些选择器,例如 伪选择器。在这个例子中,请注意,我们实际上选择的是所有相同的元素。如果我们删除四个
section
、article
、aside
和 nav
元素选择器,并将后代保留在原地,我们将得到以下内容
h1, h2, h3, h4, h5, h6,
h1, h2, h3, h4, h5, h6,
h1, h2, h3, h4, h5, h6,
h1, h2, h3, h4, h5, h6, {
color: #BADA55;
}
唯一不同的是这些标题的作用域是哪个元素。这就是 :is()
派上用场的地方,因为我们可以像这样匹配这四个元素
:is(section, article, aside, nav) {
color: #BADA55;
}
这将把 color
应用于元素本身,但我们想要的是将其应用于标题。与其为每个标题都列出它们,不如再次使用 :is()
以一次性选择它们
/* Matches any of the following headings scoped to any of the following elements. */
:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
color: #BADA55;
}
在谈到 :is()
时,值得注意的是我们还有 伪选择器,它与
:is()
做的事情完全一样。区别在哪里?:is()
的特异性将等于列表中最具体元素的特异性。同时,:where()
保持 *零* 特异性。因此,如果你想要这样的复杂选择器,更容易覆盖,请使用 :where()
代替。
嵌套选择器
最后一个示例展示了如何使用 :is()
来编写更高效的复杂选择器,很好,但现在 CSS 嵌套已成为一项广泛支持的功能,我们可以做得更好。
这些浏览器支持数据来自
,其中提供了更多详细信息。数字表示浏览器在该版本及其更高版本中支持该功能。桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
120 | 117 | 否 | 120 | 17.2 |
移动设备/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 127 | 17.2 |
CSS 嵌套使我们能够更好地了解选择器之间的关系。你知道我们在 HTML 中嵌套子元素时如何能够清楚地看到元素之间的关系吗?
<!-- Parent -->
<article>
<!-- Child -->
<img src="" alt="...">
<!-- Child -->
<div class="article-content">
<!-- Grandchild -->
<h2>Title</h2>
<!-- Grandchild -->
<p>Article content.</p>
</div>
</article>
CSS 嵌套是一种类似的方法,我们可以用来格式化 CSS 规则集。我们从一个父规则集开始,然后在其中嵌入子规则集。因此,如果我们要选择最后一个 HTML 示例中的 <h2>
元素,我们可以这样编写一个后代选择器
article h2 { /* Styles */ }
使用嵌套
article {
/* Article styles */
h2 { /* Heading 2 styles */ }
}
你可能注意到,我们可以从技术上讲再深一层,因为标题包含在另一个 .article-content
元素中。
article {
/* Article styles */
.article-content {
/* Container styles */
h2 { /* Heading 2 styles */ }
}
}
所以,总而言之,使用嵌套选择标题等同于在扁平结构中编写后代选择器。
article .article-content h2 { /* Heading 2 styles */ }
你可能想知道如何才能在嵌套格式中编写一个链式选择器。我的意思是,我们可以轻松地将一个链式选择器嵌套到另一个选择器中
article {
/* Article styles */
h2.article-content {
/* Heading 2 styles */
}
}
但我们不能像这样重新声明 article
元素选择器作为嵌套选择器
article {
/* Article styles */
/* Nope! 👎 */
article.article-element {
/* Container styles */
/* Nope! 👎 */
h2.article-content {
/* Heading 2 styles */
}
}
}
即使我们可以做到这一点,它也违背了整齐排列的嵌套显示选择器之间关系的目的。相反,我们可以使用和号 (&
) 符号来表示我们正在嵌套到的选择器。我们称之为 **嵌套选择器**。
article {
&.article-content {
/* Equates to: article.article-content */
}
}
复合选择器
我们已经讨论了不少关于层叠样式表 (Cascade) 的内容,以及它是如何使用特异性得分来决定将哪些样式应用于匹配的选择器的。之前我们看到,元素选择器比类选择器特异性低,类选择器比 ID 选择器特异性低,等等。
article { /* Specificity: 0, 0, 1 */ }
.featured { /* Specificity: 0, 1, 0 */ }
#featured { /* Specificity: 1, 0, 0 */ }
我们可以通过将选择器链接在一起——或“组合”在一起——来*提高*特异性。这样,当评估两个或多个匹配样式时,我们可以赋予我们的选择器更高的优先级。再次强调,覆盖 ID 选择器非常困难,因此我们将使用元素和类选择器来说明链接选择器。
我们可以将我们的 article
元素选择器与我们的 .featured
类选择器链接在一起,以生成更高的特异性得分。
article { /* Specificity: 0, 0, 1 */ }
.featured { /* Specificity: 0, 1, 0 */ }
articie.featured { /* Specificity: 0, 1, 1 */ }
这个新的组合选择器比其他两个单独的选择器更特异(更强大!)。请注意,在下面的演示中,组合选择器在 CSS 中位于两个单独的选择器*之前*,但在层叠样式表评估其特异性得分时,仍然胜过它们。
有趣的是,我们可以将“伪”类用在链接选择器中,作为管理特异性的一种策略。请看这个现实生活中的例子
.wp-block-theme-button .button:not(.specificity):not(.extra-specificity) { }
哇,对吧?里面有很多东西。但其理念是:.specificity
和 .extra-specificity
类选择器只是为了提高 .wp-block-theme .button
后代选择器的特异性。让我们比较一下有无这些人工类(在匹配中被 :not()
包含)的特异性得分。
.wp-block-theme-button .button {
/* Specificity: 0, 2, 0 */
}
.wp-block-theme-button .button:not(.specificity) {
/* Specificity: 0, 3, 0 */
}
.wp-block-theme-button .button:not(.specificity):not(.extra-specificity {
/* Specificity: 0, 4, 0 */
}
很有趣!我不确定是否会在我自己的 CSS 中使用它,但它比使用 !important
关键字更不容易产生副作用,而 !important
与 ID 选择器一样难覆盖。
组合器
如果说选择器是我们在 CSS 中选择“什么”,那么你或许可以将 CSS 组合器视为选择“如何”。它们用于编写将其他选择器组合在一起以定位元素的选择器。盗梦空间!
“组合器”这个名称很好,因为它准确地传达了我们能够*组合选择器*的多种不同方式。为什么我们需要组合选择器?正如我们之前在讨论链接选择器时所讨论的那样,有两种常见的场景,我们会想要这样做
- 当我们想要*提高*所选内容的特异性时。
- 当我们想要根据条件选择元素时。
让我们回顾一下 CSS 中提供的多种类型的组合器,以应对这两种情况以及链接选择器。
后代组合器
我们称之为“后代”组合器,因为我们使用它来选择其他元素内部的元素,有点像这样
/* Selects all elements in .parent with .child class */
.parent .child {}
…它将在以下 HTML 示例中选择所有具有 .child
类的元素
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="friend"></div>
<div class="child"></div>
<div class="child"></div>
</div>
看到那个具有 .friend
类名的元素了吗?它是 .parent
元素内部的唯一一个未被 .parent .child {}
后代组合器选择的元素,因为它不匹配 .child
,即使它也是 .parent
元素的后代。
子代组合器
子代组合器实际上只是后代组合器的一个分支,只是它比后代组合器更特异,因为它只选择元素的直接子代,而不是任何后代。
让我们修改一下我们最后看过的 HTML 示例,在其中引入一个更深层级的后代元素,比如 .grandchild
<div class="parent">
<div class="child"></div>
<div class="child">
<div class="grandchild"></div>
</div>
<div class="child"></div>
<div class="child"></div>
</div>
因此,我们有一个 .parent
对应四个 .child
元素,其中一个包含一个 .grandchild
元素。
也许我们想要选择 .child
元素,而不无意中选择第二个 .child
元素的 .grandchild
。这就是子代组合器可以做的事情。以下所有子代组合器都将实现相同的效果
/* Select only the "direct" children of .parent */
.parent > .child {}
.parent > div {}
.parent > * {}
看到我们*是如何结合不同的选择器类型来进行选择的*了吗?我们正在进行组合,该死!我们只是根据我们正在结合的子代选择器的类型,以略微不同的方式进行组合。
/* Select only the "direct" children of .parent */
.parent > #child { /* direct child with #child ID */
.parent > .child { /* direct child with .child class */ }
.parent > div { /* direct child div elements */ }
.parent > * { /* all direct child elements */ }
非常棒的是,我们不仅有一种方法可以只选择元素的直接子代,而且可以根据选择器类型来控制其特异性。例如,ID 选择器比类选择器更特异,类选择器比元素选择器更特异,等等。
一般兄弟组合器
如果两个元素共享同一个父元素,那么它们就是兄弟姐妹。我们在讨论后代组合器时,顺便提到了一个例子。让我们修改一下那个示例的类名,使兄弟关系更加清晰
<div class="parent">
<div class="brother"></div>
<div class="sister"></div>
</div>
这就是我们可以选择 .sister
元素的方法,只要它前面有一个具有类 .brother
的兄弟元素。
/* Select .sister only if follows .brother */
.brother ~ .sister { }
波浪号符号 (~
) 表示这是一个兄弟组合器。
.sister
是否紧跟在 .brother
之后并不重要——只要 .sister
位于 brother
之后,并且它们共享同一个父元素,它就会被选择。让我们看一个更复杂的 HTML 示例
<main class="parent">
<!-- .sister immediately after .brother -->
<div class="brother"></div>
<div class="sister"></div>
<!-- .sister immediately after .brother -->
<div class="brother"></div>
<div class="sister"></div>
<!-- .sister immediately after .sister -->
<div class="sister"></div>
<!-- .cousin immediately after .brother -->
<div class="brother"></div>
<div class="cousin">
<!-- .sister contained in a .cousin -->
<div class="sister"></div>
</div>
</main>
我们编写的兄弟组合器只选择了前三个 .sister
元素,因为它们是唯一位于 .brother
元素之后且共享同一个父元素的元素——即使第三个 .sister
位于另一个 sister 之后!第四个 .sister
位于一个 .cousin
元素内,这阻止了它与选择器匹配。
让我们在上下文中看看。因此,我们可以使用元素选择器选择*所有元素*,因为 HTML 中的每个元素都是一个 div
从那里,我们可以使用类选择器选择*只有兄弟元素*,赋予它们不同的背景颜色
我们也可以使用类选择器,为所有具有 .sister
类的元素设置不同的背景颜色
最后,我们可以使用一般兄弟组合器来选择*只有紧跟在兄弟元素之后的 sister 元素*。
你注意到最后一个 .sister
元素的背景颜色仍然是绿色,而其他元素变成了紫色了吗?这是因为它是在所有 .sister
元素中唯一一个*没有*与 .brother
元素共享同一个 .parent
元素的元素。
相邻组合器
信不信由你,我们可以使用相邻组合器对所选元素进行更*精确*的控制。我们刚刚看到的通用兄弟选择器将选择页面上所有 .sister
元素,只要它们与 .brother
共享同一个父元素,并且位于 .brother
*之后*。
相邻组合器与之不同的是,它会选择紧跟在另一个元素之后的任何元素。还记得最后一个 .sister
元素没有匹配吗,因为它包含在一个不同的父元素(即 .cousin
)中?嗯,我们可以使用相邻组合器来选择它
/* Select .sister only if directly follows .brother */
.brother + .sister { }
注意,当我们把它添加到最后一个示例中时会发生什么
前两个 .sister
元素改变了颜色!这是因为它们是唯一紧跟在 .brother
元素之后的 sister 元素。第三个 .sister
元素紧跟在另一个 .sister
元素之后,第四个 .sister
元素包含在一个 .cousin
元素内,这阻止了它们与选择器匹配。
了解更多关于 CSS 选择器的知识
- 选择器 (CSS-Tricks 年鉴)
- 学习 CSS:选择器 (Mozilla 开发者网络)
- 高级选择器指南 (ModernCSS.dev)
- 选择器 (web.dev)
- 选择器说明:将选择器翻译成英语 (Kitty Giraudel)
- CSS 餐厅 (互动游戏)
目录
参考
您在这里阅读的大部分内容都是从我们在 CSS-Tricks 上发布的文章中提取的信息,这些文章在整个指南中都有链接。除了这些文章,以下资源对整理本指南非常有帮助。
- CSS 选择器级别 4 (W3C)
- 3.2.6 全局属性 (HTML Living Standard)
感谢您的文章!
也许您还可以提到 owln 选择器?
https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/
它很酷,但我在这里错过了。
我只想说这些关于 CSS 选择器的提示非常有用!它们确实提高了我对 CSS 在项目中的理解和应用。感谢您分享您的知识和专业技能。继续努力,干得好。