嵌套是应用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和相似工具依然是大多数开发人员工具包的重要组成部分。
以上就是本文的全部内容。如果对你有所帮忙,欢送点赞、珍藏、转发~