引言
将近20年,CSS终于在所有现代浏览器实现了原生嵌套语法,是时候淘汰less/sass等预处理器了
来自 Web 开发者的呼声
2012年4月13日,CodePen 的联合创始人 Chris Coyier 抱怨 CSS 的类名不支持命名空间,导致要写好多重复的选择器。
2016年2月2日,微软的项目经理 Kenneth Auchenberg 说如果 CSS 支持了变量和嵌套,他将不再使用预处理器。
2016年12月8日,《CSS揭秘》的作者 Lea Verou 调研了使用 CSS 预处理器的首要原因(单选题),有 1838 个人参与了投票,最终并列第一的两个理由是嵌套和变量。她觉得是时候该重新考虑 CSS 原生嵌套的问题了。
2017年7月13日,集设计和开发才能于一身的 UI/UX 自由工作者 Sara Soueidan 说嵌套是她最想要的 CSS 功能。
2017年8月15日,node-inspect 的作者 Jan Olaf Krems 说 cssnext 把嵌套定义成了“明天的 CSS”,但他还是想看到原生的 CSS 嵌套,毕竟 JS 的生态系统已经证明避免“每个人都使用自己的半标准语言”绝对是健康的。
2018年2月23日,Lea Verou 再次发声,说她现在还在用 CSS 预处理器写嵌套,一旦 CSS 支持了原生嵌套,她就果断弃用预处理。
2018年5月25日,postcss-preset-env 的作者 Jonathan Neal 再次提议重新考虑下让 CSS 支持原生嵌套(也就是本文章的切入点),这引来了一波热议。
在嵌套之前,每个选择器都需要单独声明,相互之间没有联系。这会导致重复、样式表冗余和开发体验分散。
示例
嵌套之前的示例:
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
嵌套之后,选择器可以继续编写,并且与之相关的样式规则可以在其中进行分组。
嵌套之后的示例
.nesting { color: hotpink; >.is { color: rebeccapurple; >.awesome { color: deeppink; } } }
<div class="nesting"> <div class="is"> <div class="awesome"></div> </div> </div>
嵌套可以帮助开发人员减少重复选择器的需求,同时还可以将相关元素的样式规则放在一起,提高样式与目标HTML匹配的能力。如果在前面的示例中删除了.nesting
组件,您可以删除整个嵌套组,而不是在文件中搜索相关的选择器实例。
嵌套的作用
嵌套可以帮助:
- 组织代码
- 减小文件大小
- 进行重构
嵌套从Chrome 112版本开始提供支持,并且在Safari技术预览版162中也可以尝试使用。
开始使用CSS嵌套
在本文的其余部分,我们将使用以下演示沙箱来帮助您可视化所选择的内容。在默认状态下,没有选择任何内容,所有内容都可见。通过选择不同的形状和大小,您可以练习语法并查看其效果。
沙箱中有圆、三角形和正方形。其中一些是小的,中等的或大的。其他的是蓝色的、粉色的或紫色的。它们都在.demo
容器元素内。以下是您将要选择的HTML元素的预览。
<div class="demo"> <div class="sm triangle pink"></div> <div class="sm triangle blue"></div> <div class="square blue"></div> <div class="sm square pink"></div> <div class="sm square blue"></div> <div class="circle pink"></div> … </div>
嵌套示例
CSS嵌套允许您在一个选择器的上下文中定义另一个选择器的样式。
.parent { color: blue; .child { color: red; } }
在此示例中,.child
类选择器嵌套在.parent
类选择器内部。这意味着嵌套的.child
选择器只会应用于具有.parent
类的元素的子元素。
这个示例也可以使用&
符号来显式表示父类应该放置在哪里。
.parent { color: blue; & .child { color: red; } }
这两个示例在功能上是等效的,并且可以通过更多高级示例来进一步理解它们的用法。
选择圆形
对于第一个示例,任务是为演示中的圆形添加淡化和模糊样式。
不使用嵌套,CSS现在的写法:
.demo .circle { opacity: .25; filter: blur(25px); }
使用嵌套,有两种有效的方式:
/* & is explicitly placed in front of .circle */ .demo { & .circle { opacity: .25; filter: blur(25px); } }
或者
/* & + " " space is added for you */ .demo { .circle { opacity: .25; filter: blur(25px); } }
结果,所有具有.circle
类的元素在.demo
内部被模糊处理,几乎不可见:
<div class="demo"> <div class="sm triangle pink"></div> <div class="sm triangle blue"></div> <div class="square blue"></div> <div class="sm square pink"></div> <div class="sm square blue"></div> <div class="circle pink"></div> <div class="sm circle blue"></div> <div class="lg circle purple"></div> <div class="triangle blue"></div> <div class="sm circle pink"></div> <div class="square purple"></div> <div class="sm triangle purple"></div> <div class="sm square pink"></div> <div class="sm square purple"></div> <div class="sm circle blue"></div> <div class="sm circle pink"></div> <div class="lg triangle pink"></div> <div class="sm square pink"></div> <div class="sm square purple"></div> <div class="sm circle blue"></div> <div class="square pink"></div> <div class="sm square pink"></div> <div class="sm square purple"></div> <div class="sm circle blue"></div> </div>