查看原文
其他

现代CSS:原生 CSS 嵌套快速入门

小懒 FED实验室 2024-02-12
关注下方公众号,获取更多现代CSS系列文章

随着Firefox 117版本的发布,原生 CSS 嵌套(Native CSS nesting)已经被所有现代桌面浏览器所支持!🎉,但是请注意,移动端浏览器支持的还很有限。

1.原生 CSS 嵌套

原生 CSS 嵌套可以像 SASS、LESS 预处理器一样,将相关的选择器组合在一起,从而减少需要编写的规则数量。它可以节省打字时间,并使语法更易于阅读和维护。您可以将选择器嵌套到任意深度,但要小心不要超过两层或三层。嵌套深度没有技术限制,但它会使代码更难以阅读,并且生成的 CSS 可能会变得不必要的冗长。

.button {
background-color: red;

&.warning {
background-color: blue;
}

& .icon {
width: 1rem;
height: 1rem;
}
}

虽然原生 CSS 嵌套语法在过去几年中不断发展,使大多数 Web 开发人员感到满意,但不要指望所有 SCSS 代码都能像您期望的那样直接工作。

2.原生 CSS 嵌套规则

您可以将任何选择器嵌套在另一个选择器中,但它必须以符号开头,例如 &, .(类选择器)、#(ID选择器)、@(对于媒体查询)、:::+~>[。换句话说,它不能是对 HTML 元素的直接引用。下面的代码是无效的,不会对 input 元素选择器进行解析:

.parent {
color: red;

input {
margin: 1em;
}
}
/* Invalid, because "input" is an identifier. */

解决此问题的最简单方法是使用与号 ( &),它以与 Sass 相同的方式引用当前选择器。

2.1.& 符号的使用

.parent {
color: red;

& input {
margin: 1em;
}

/* use pseudo-elements and pseudo-classes */
&::after {}

&:hover {}

&:target {}
}
/* valid, no longer starts with an identifier */

或者,您可以使用其中之一:

  • > input:只对子元素生效

  • :is(input):将选择器列表作为参数,并选择该列表中任意一个选择器可以选择的元素

  • :where(input):优先级总是为 0

它们都可以在这个简单的示例中工作,但是稍后您可能会遇到更复杂的样式表的特异性问题。

它还&允许您在父选择器上定位伪元素和伪类。例如:

p.my-element {

&::after {}

&:hover {}

&:target {}
}

请注意,& 可以在选择器中的任何位置使用。例如:

.child1 {
.parent3 & {
color: red;
}
}

这将转换为以下非嵌套语法:

.parent3 .child1 { color: red; }

您甚至可以在选择器中使用多个 & 符号:

ul {
& li & {
color: blue;
}
}

这将以嵌套 <ul> 元素 ( ul li ul) 为目标,但如果您想保持理智,我建议不要使用它!

2.2.@ 符号的使用

嵌套媒体查询示例:

p {
color: cyan;
@media (min-width: 800px) {
color: purple;
}
}

3.原生 CSS 嵌套陷阱

3.1.场景一:父选择器包装在 :is()

原生 CSS 嵌套将父选择器包装在 :is() 中,这可能会导致与 Sass 输出的差异,比如以下嵌套代码:

.parent1, #parent2 {
.child1 {

}
}

当它在浏览器中解析时,它实际上变成以下内容:

:is(.parent1, #parent2) .child1 {

}

Sass 将相同的代码编译为:

.parent1 .child1,
#parent2 .child1 {

}

3.2.场景二:& 符号后置

您可能还会遇到一个更微妙的问题。考虑一下:

.parent .child {
.grandparent & {}
}

原生 CSS 等效项是:

.grandparent :is(.parent .child) {}

这与以下错误排序的 HTML 元素匹配:

<div class="parent">
<div class="grandparent">
<div class="child">MATCH</div>
</div>
</div>

Sass 中的情况并非如此,它编译为:.grandparent .parent .child {} 上面的 HTML 没有样式化,因为元素类不遵循严格的grandparent、parent、 和child顺序。

3.3.场景三:字符串替换

Sass 使用字符串替换,因此如下所示的声明是有效的,并且与类的任何元素相匹配 .btn-primary

.btn {
&-primary {
color: blue;
}
}

但是原生 CSS 嵌套会忽略&-space选择器。

4.CSS 预处理器还需要吗?

从短期来看,现有的 CSS 预处理器仍然至关重要。Sass 开发团队宣布,他们将支持 .css 文件中的原生 CSS 嵌套,并按原样输出代码。他们将一如既往地编译嵌套 SCSS 代码,以避免破坏现有代码库,但当全球浏览器支持率达到 98% 时,他们将开始输出 :is() 选择器。

我猜想,PostCSS 插件等预处理器目前会扩展嵌套代码,但随着浏览器支持的普及,就会取消这一功能。当然,使用预处理器还有其他很好的理由,比如将部分代码捆绑到一个文件中,以及对代码进行精简。但如果嵌套是你唯一需要的功能,你当然可以考虑在较小的项目中使用原生 CSS。

5.总结

CSS 嵌套是最有用、最实用的预处理器功能之一。浏览器供应商努力创造了一个与 CSS 非常相似的原生 CSS 版本,以满足网络开发人员的需求。虽然两者之间存在细微差别,而且在使用(过于)复杂的选择器时可能会遇到不寻常的特殊性问题,但很少有代码库需要进行彻底修改。

原生嵌套可能会让你重新考虑是否需要 CSS 预处理器,但它们仍能提供其他好处。Sass 和类似工具仍然是大多数开发者工具包的重要组成部分。

大家都在看

继续滑动看下一个

现代CSS:原生 CSS 嵌套快速入门

小懒 FED实验室
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存