嵌套是应用 Sass 等 CSS 预处理器的外围起因之一。当初,该性能曾经以相似的语法呈现在规范浏览器 CSS 中。你是否在构建零碎时放弃对预处理器的依赖?
CSS 嵌套能够节俭输出工夫,并使语法更易于浏览和保护。迄今为止,你必须像这样键入残缺的选择器门路:
.parent1 .child1,
.parent2 .child1 {color: red;}
.parent1 .child2,
.parent2 .child2 {color: green;}
.parent1 .child2:hover,
.parent2 .child2:hover {color: blue;}
当初,你能够将子选择器嵌套在父选择器中,比方:
.parent1, .parent2 {
.child1 {color: red;}
.child2 {
color: green;
&:hover {color: blue;}
}
}
你能够嵌套任意层级的选择器,但要留神不要超过两到三级。嵌套层级没有技术层面的限度,然而会让代码更难浏览,并且让最终 CSS 变得很简短。
直到 2023 年四月,暂没有浏览器反对 CSS 嵌套语法。你须要应用 CSS 预处理器(如 Sass、Less 或 PostCSS)进行构建步骤,以便将嵌套代码转换为惯例的全选择器语法。嵌套性能现已在 Chrome 112+ 和 Safari 16.5+ 中实现,Firefox 将在 2023 年晚些时候提供反对。
CSS 原生嵌套规定
你能够将任何选择器嵌套到另一个选择器中,但必须以符号结尾,如 &
,.
(用于 HTML class
),#
(用于 HTML id
),@
(用于媒体查问),:
,::
,*
,+
,~
,>
,或 [
。换句话说,它不能间接援用 HTML 元素。上面的代码有效,<p>
选择器不会被解析:
.parent1 {
/* FAILS */
p {color: blue;}
}
修复该问题最简略的办法就是应用&
,其与 Sass 雷同的形式援用以后选择器:
.parent1 {
/* WORKS */
& p {color: blue;}
}
或者,能够这么解决:
> p
– 但这将仅对.parent1
的间接子元素进行款式调整:is(p)
– 然而:is()
应用最优先选择器的优先级:where(p)
– 然而:where()
的优先级为 0
在这个简略的示例中,它们都能够工作,但在当前应用更简单的样式表时,你可能会遇到优先级问题。
&
还容许你在父选择器上定位伪元素和伪类。例如:
p.my-element {&::after {}
&:hover {}
&:target {}}
如果你不应用 &
,你的指标将是选择器的所有子元素,而不是p.my-element
自身。(在 Sass 中也会呈现同样的状况)。
须要留神的是,你能够在选择器的任何地位应用&
,比方:
.child1 {
.parent3 & {color: red;}
}
这会转换为下列非嵌套语法:
.parent3 .child1 {color: red;}
你甚至能够在一个选择器中应用多个 &
符:
ul {
& li & {color: blue;}
}
这会作用于嵌套的 <ul>
元素(ul li ul
),如果你不想被逼疯我倡议还是不要这么应用了!
最初,你能够嵌套媒体查问。上面的代码为段落元素利用了 cyan
色彩,除非浏览器宽度至多为 800px,否则将变为purple
:
p {
color: cyan;
@media (min-width: 800px) {color: purple;}
}
CSS 原生嵌套问题
原生嵌套在 :is()
中包裹父选择器,这可能会导致与 Sass 输入的差别。
思考下列的嵌套代码:
.parent1, #parent2 {.child1 {}
}
在浏览器中解析时,这实际上变成了以下内容:
:is(.parent1, #parent2) .child1 {}
.parent1
中的 .child1
元素的优先级为 101,因为 :is()
应用了其最优先选择器的优先级 – 在本例中,是#parent2
ID。
Sass 编译的代码与此雷同:
.parent1 .child1,
#parent2 .child1 {}
在本例中,.parent1
中的 .child1
元素的特异性为 002,因为它匹配两个类(#parent2
被疏忽)。它的选择器比原生选项的优先级低,在级联中被笼罩的可能性更大。
你可能还会遇到一个更奥妙的问题。思考下列代码:
.parent .child {.grandparent & {}
}
原生 CSS 等价于:
.grandparent :is(.parent .child) {}
这与下列排序谬误的 HTML 元素相匹配:
<div class="parent">
<div class="grandparent">
<div class="child">MATCH</div>
</div>
</div>
因为 CSS 解析器会执行以下操作,因而 MATCH
会扭转款式:
- 在 DOM 层次结构中的任意地位,找到所有类为
child
的元素,同时先人元素的类为parent
。 - 在找到蕴含
MATCH
的元素后,解析器会查看该元素是否有一个先人为grandparent
的元素 – 同样是在 DOM 层次结构中的任意地位。找到后,解析器会相应地对该元素利用款式。
在 Sass 中不是这种状况,最终会编译成这样:
.grandparent .parent .child {}
下面的 HTML 没有款式化,因为元素的类没有遵循严格的 grandparent
、parent
和child
程序。
最初,Sass 应用字符串替换,所以像上面这样的申明是无效的,能够匹配任何具备 outer-space
类的元素:
.outer {&-space { color: black;}
}
而原生 CSS 会疏忽 &-space
选择器。
还须要 CSS 预处理器吗
在短期内,现有的 CSS 预处理器依然必不可少。
Sass 开发团队曾经发表,他们将反对 .css
文件中的原生 CSS 嵌套,并按原样输入代码。他们将判若两人地编译嵌套的 SCSS 代码,以防止毁坏现有代码库,但当寰球浏览器支持率达到 98% 时,他们将开始输入 :is()
选择器。
我猜想 PostCSS 插件等预处理器目前会扩大嵌套代码,但当浏览器支持率越来越高时,就会移除该性能。
当然,应用预处理器还有其余很好的理由 – 比方将局部代码捆绑到繁多文件中,以及精简代码。但如果嵌套是你惟一须要的性能,那么你当然能够思考在小型我的项目中应用本地 CSS。
总结
CSS 嵌套是最有用、最实用的预处理器性能之一。浏览器供应商努力创造了一个本地 CSS 版本,其相似性足以让 Web 开发人员称心。尽管两者之间存在细微差别,而且在应用(过于)简单的选择器时可能会遇到不寻常的优先级问题,但很少有代码库须要进行彻底批改。
原生嵌套可能会让你重新考虑对 CSS 预处理器的需要,但它们仍能提供其余益处。Sass 和相似工具依然是大多数开发人员工具包的重要组成部分。
以上就是本文的全部内容。如果对你有所帮忙,欢送点赞、珍藏、转发~