现在已经有 CSS 范围作用域的工作草案规范 了。除了一个奇怪的时期,<style scoped>
曾经被发布,随后又从规范(和浏览器)中删除,这是范围作用域提案取得的最远进展(Level 1 规范 一直没有得到任何进展)。
这个提案 来自 Miriam Suzanne。
基础知识
<div class="media">
<img alt="Proper alt." src="...">
<div class="content">
<p>...</p>
</div>
</div>
如果我把这段 HTML 代码视为一个“组件”,那么能够为其编写非常明确地只针对它的样式会非常不错。这就是 @scope
的作用,所以……
@scope (.media) {
:scope {
display: grid;
grid-template-columns: 50px 1fr;
}
img {
filter: grayscale(100%);
border-radius: 50%;
}
.content { ... }
}
我喜欢它的地方在于
- 这段 CSS 代码非常明确地只针对这个媒体组件。它的阅读方式和维护方式都体现了这一点。
- 我不需要为
<img>
想出一个名称和类。我在那里应用样式,而不会“泄漏”到其他图像。
但是等等,这难道不就像在选择器前面加上父级类一样吗?
它有点像……比如我们也可以这样写
.media {
}
.media img {
}
.media .content {
}
现在我们已经将内容限制在媒体组件内部了。这有点重复,但是随着 原生 CSS 嵌套 的到来,它就变成了这样
.media {
& img {
}
& .content {
}
}
所以是的,我认为嵌套可以处理一些基本的范围作用域类型,但是这个新的范围作用域提案有一些非常独特的东西。
一个独特的特性是 “甜甜圈范围作用域”,这意味着我可以在想要的地方停止范围作用域。也许我想让我的范围作用域在特定的类处停止
@scope (.media) to (.content) {
p { }
}
现在我可以编写样式,而不会干扰我不希望它们干扰的区域。也许
<div class="media">
<img alt="Proper alt." src="...">
<p>This is stylable in scope.</p>
<div class="content">
<p>This is NOT styleable in scope.</p>
</div>
</div>
但这并不是这个新规范解决的唯一独特问题。我认为 Miriam 提出的“最近祖先”情况也许是最有趣的事情。 我将带您前往博文 阅读关于此内容的信息——我们还没有一个好的工具来解决这个问题,这真是太奇怪了。
这里有很多东西需要你思考,尤其是在你想到更复杂的情况时,比如多个重叠的范围作用域以及嵌套语法如何与范围作用域交互。幸运的是,Miriam 正在非常清晰地记录这些内容。
第四个示例是 SCSS/Less,而不是有效的原生嵌套直接选择器。后者(如所提议的)必须以
&
开头哦,我以为如果只是进行简单的嵌套选择器,就可以省略 &。我可能错了
为什么浏览器应该笨到无法在没有必要的 & 的情况下处理它?!
我希望如此,但为了避免无限前瞻以区分声明和嵌套选择器,它不会这样做。
规范),请参阅上面的“为什么不能所有内容都直接嵌套?”
令我非常难过的是,这将使将一组规则集用附加选择器包装(嵌套)的重构步骤变得不平凡且繁琐,但从解析器性能的角度来看,这个理由是有道理的:每个声明都必须处理两次,第一次是为了找到结束的
;
或{
,然后分别将其解析为声明/选择器。有一种方法试图使嵌套前缀可选,但没有进行详细调查:#5746
对于 @nest(不是直接嵌套)也存在类似的问题:#5738
他们提出的
to
子句(如@scope (.media) to (.content)
示例中所示)可以派上用场。如果将“to”一词更改为“until”,则会减少混淆。
不同意,如果我从我的 .home 跑到 .stopsign,那就是我停止的地方,我不会超越它。对我来说很有道理。
哇。我们已经期待这个功能很多年了……
我一直回到这里,希望提议的语法看起来不那么奇怪。我理解它,但我确实可以看到它的使用会导致大型项目中出现完全混乱。
将主要用于环境检查(媒体查询、支持等)的 @ 语法与选择器过程混合,让我想起了最后的浏览器目标补丁。与感觉更符合 CSS 的嵌套提案相比,整个事情看起来有点糟糕。