使用 CSS 嵌套
该 CSS 嵌套 模块允许您编写样式表,使其更易于阅读、更模块化且更易于维护。由于您没有不断重复选择器,因此文件大小也可以减小。
CSS 嵌套与 Sass 等 CSS 预处理器不同,因为它由浏览器解析,而不是由 CSS 预处理器预编译。此外,在 CSS 嵌套中,&
嵌套选择器的特异性 类似于 :is()
函数;它是使用关联选择器列表中最高的特异性计算的。
本指南展示了在 CSS 中排列嵌套的不同方法。
子选择器
您可以使用 CSS 嵌套创建父元素的子选择器,然后可以使用这些子选择器来定位特定父元素的子元素。这可以通过使用或不使用 &
嵌套选择器 来完成。
在某些情况下,使用 &
嵌套选择器可能是必要的或有帮助的
/* Without nesting selector */
parent {
/* parent styles */
child {
/* child of parent styles */
}
}
/* With nesting selector */
parent {
/* parent styles */
& child {
/* child of parent styles */
}
}
/* the browser will parse both of these as */
parent {
/* parent styles */
}
parent child {
/* child of parent styles */
}
示例
在这些示例中,一个不使用 &
嵌套选择器,另一个使用 &
嵌套选择器,<label>
内部的 <input>
的样式与作为 <label>
同级元素的 <input>
的样式不同。这演示了省略 &
嵌套选择器的影响。
注意:此示例演示了实现原始规范与当前嵌套规范的浏览器中的不同输出。Chrome 或 Safari 中实现的原始(2023 年 8 月之前的)嵌套规范需要 &
嵌套组合器。如果您的浏览器支持当前规范,则两个示例的输出都与第二个示例的输出匹配。
不使用嵌套选择器
HTML
<form>
<label for="name">Name:
<input type="text" id="name" />
</label>
<label for="email">email:</label>
<input type="text" id="email" />
</form>
CSS
input {
/* styles for input not in a label */
border: tomato 2px solid;
}
label {
/* styles for label */
font-family: system-ui;
font-size: 1.25rem;
input {
/* styles for input in a label */
border: blue 2px dashed;
}
}
结果
使用嵌套选择器
HTML
<form>
<label for="name">Name:
<input type="text" id="name" />
</label>
<label for="email">email:</label>
<input type="text" id="email" />
</form>
CSS
input {
/* styles for input not in a label */
border: tomato 2px solid;
}
label {
/* styles for label */
font-family: system-ui;
font-size: 1.25rem;
& input {
/* styles for input in a label */
border: blue 2px dashed;
}
}
结果
组合器
CSS 组合器 也可以在使用或不使用 &
嵌套选择器的情况下使用。
示例
嵌套同级组合器
在此示例中,每个 <h2>
之后的第一个段落使用 下一个同级组合器 (+
) 和 CSS 嵌套进行定位。
HTML
<h2>Heading</h2>
<p>This is the first paragraph.</p>
<p>This is the second paragraph.</p>
CSS
h2 {
color: tomato;
+ p {
color: white;
background-color: black;
}
}
/* this code can also be written with the & nesting selector */
/*
h2 {
color: tomato;
& + p {
color: white;
background-color: black;
}
}
*/
结果
复合选择器
在嵌套 CSS 中使用 复合选择器 时,**必须**使用 &
嵌套选择器。这是因为浏览器会在不使用 &
嵌套选择器的选择器之间自动添加空格。
为了定位具有 class="a b"
的元素,需要 &
嵌套选择器,否则空格将破坏复合选择器。
.a {
/* styles for element with class="a" */
.b {
/* styles for element with class="b" which is a descendant of class="a" */
}
&.b {
/* styles for element with class="a b" */
}
}
/* the browser parses this as */
.a {
/* styles for element with class="a" */
}
.a .b {
/* styles for element with class="b" which is a descendant of class="a" */
}
.a.b {
/* styles for element with class="a b" */
}
示例
嵌套和复合选择器
在此示例中,&
嵌套选择器用于创建复合选择器,以设置具有多个类的元素的样式。
HTML
<div class="notices">
<div class="notice">
<h2 class="notice-heading">Notice</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
<div class="notice warning">
<h2 class="warning-heading">Warning</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
<div class="notice success">
<h2 class="success-heading">Success</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
</div>
CSS
.notices
的样式,使用 Flexbox 布局 创建一列。
.notices {
display: flex;
flex-direction: column;
gap: 0.5rem;
width: 90%;
margin: auto;
}
在下面的 CSS 代码中,嵌套用于创建带和不带&
的复合选择器。顶级选择器定义了具有class="notice"
元素的基本样式。然后使用&
嵌套选择器为具有class="notice warning"
或class="notice success"
的元素创建复合选择器。此外,在选择器.notice .notice-heading::before
中可以看到使用嵌套创建复合选择器而不显式使用&
。
.notice {
width: 90%;
justify-content: center;
border-radius: 1rem;
border: black solid 2px;
background-color: #ffc107;
color: black;
padding: 1rem;
.notice-heading::before {
/* equivalent to `.notice .notice-heading::before` */
content: "ℹ︎ ";
}
&.warning {
/* equivalent to `.notice.warning` */
background-color: #d81b60;
border-color: #d81b60;
color: white;
.warning-heading::before {
/* equivalent to `.notice.warning .warning-heading::before` */
content: "! ";
}
}
&.success {
/* equivalent to `.notice.success` */
background-color: #004d40;
border-color: #004d40;
color: white;
.success-heading::before {
/* equivalent to `.notice.success .success-heading::before` */
content: "✓ ";
}
}
}
结果
附加嵌套选择器
&
嵌套选择器也可以附加到嵌套选择器,这会反转上下文。
当我们有子元素的样式,并且当父元素被赋予不同的类时这些样式会发生变化时,这很有用。
<div>
<span class="foo">text</span>
</div>
与
<div class="bar">
<span class="foo">text</span>
</div>
.foo {
/* .foo styles */
.bar & {
/* .bar .foo styles */
}
}
示例
附加嵌套选择器
在这个例子中,有 3 张卡片,其中一张是特色卡片。除了特色卡片的标题将具有替代颜色外,所有卡片都完全相同。通过附加&
嵌套选择器,.featured .h2
的样式可以嵌套在h2
的样式中。
HTML
<div class="wrapper">
<article class="card">
<h2>Card 1</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
<article class="card featured">
<h2>Card 2</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
<article class="card">
<h2>Card 3</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
</div>
CSS
.wrapper {
display: flex;
flex-direction: row;
gap: 0.25rem;
font-family: system-ui;
}
在以下 CSS 中,我们正在创建.card
和.card h2
的样式。然后,在h2
样式块中,我们将.featured
类与附加的&
嵌套选择器嵌套,这会为.card :is(.featured h2)
创建样式,这等效于:is(.card h2):is(.featured h2)
。
.card {
padding: 0.5rem;
border: 1px solid black;
border-radius: 0.5rem;
& h2 {
/* equivalent to `.card h2` */
color: slateblue;
.featured & {
/* equivalent to `:is(.card h2):is(.featured h2)` */
color: tomato;
}
}
}
结果
连接(不可行)
在 Sass 等 CSS 预处理器中,可以使用嵌套将字符串连接起来以创建新的类。这在 BEM 等 CSS 方法中很常见。
.component {
&__child-element {
}
}
/* In Sass this becomes */
.component__child-element {
}
在复合选择器中,类型选择器必须放在第一位。编写&Element
(一个类型选择器)会使 CSS 选择器和整个选择器块无效。由于类型选择器必须放在第一位,因此复合选择器必须写成Element&
。
.my-class {
element& {
}
}
/* the browser parses this to become a compound selector */
.my-class {
}
element.my-class {
}
无效的嵌套样式规则
如果嵌套的 CSS 规则无效,则所有包含的样式都将被忽略。这不会影响父级或前面的规则。
在下面的示例中,有一个无效的选择器(%
不是选择器的有效字符)。包含此选择器的规则将被忽略,但后续的有效规则不会。
.parent {
/* .parent styles these work fine */
& %invalid {
/* %invalid styles all of which are ignored */
}
& .valid {
/* .parent .valid styles these work fine */
}
}