为了修复 CSS 嵌套的一些奇怪问题,CSS 工作组决定向 CSS 嵌套规范中添加 CSSNestedDeclarations
接口。除了这项改进之外,样式规则后面的声明也不再向上移动,此外还进行了一些其他改进。
这些更改从 Chrome 130 版开始生效,并且已可在 Firefox Nightly 132 和 Safari Technology Preview 204 中进行测试。
不使用 CSSNestedDeclarations
的 CSS 嵌套问题
CSS 嵌套的注意事项之一是,最初,以下代码段的运作方式与您最初预期的可能不一致:
.foo {
width: fit-content;
@media screen {
background-color: red;
}
background-color: green;
}
查看代码后,您可能会认为 <div class=foo>
元素有一个 green
background-color
,因为 background-color: green;
声明位于最后。但在 130 版之前的 Chrome 中,情况并非如此。在这些版本中,由于不支持 CSSNestedDeclarations
,因此该元素的 background-color
为 red
。
解析 Chrome 130 之前使用的实际规则后,结果如下所示:
.foo {
width: fit-content;
background-color: green;
@media screen {
& {
background-color: red;
}
}
}
解析后的 CSS 发生了两项更改:
background-color: green;
已向上移,以加入其他两个声明。- 嵌套的
CSSMediaRule
已重写,以使用&
选择器将其声明封装在额外的CSSStyleRule
中。
您在这里会看到的另一项典型更改是,解析器会舍弃不支持的属性。
您可以通过从 CSSStyleRule
中读回 cssText
,自行检查“解析后的 CSS”。
为什么要重写此 CSS?
如需了解发生这种内部重写的原因,您需要了解此 CSSStyleRule
在 CSS 对象模型 (CSSOM) 中的表示方式。
在 130 之前的 Chrome 版本中,之前分享的 CSS 代码段会序列化为以下内容:
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.resolvedSelectorText = ".foo"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: green
.cssRules (CSSRuleList, 1) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(.foo)"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 1) =
- background-color: red
在本例中,CSSStyleRule
的所有属性中,以下两个属性相关:
style
属性,它是一个表示声明的CSSStyleDeclaration
实例。cssRules
属性,它是一个CSSRuleList
,用于存储所有嵌套的CSSRule
对象。
由于 CSS 代码段中的所有声明最终都会位于 CSStyleRule
的 style
属性中,因此会丢失信息。查看 style
属性时,不太清楚 background-color: green
是在嵌套的 CSSMediaRule
之后声明的。
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: green
.cssRules (CSSRuleList, 1) =
↳ …
这会带来问题,因为 CSS 引擎必须能够区分出现在样式规则内容开头的属性与与其他规则交错出现的属性,才能正常运行。
至于 CSSMediaRule
中的声明突然被封装在 CSSStyleRule
中:这是因为 CSSMediaRule
并非旨在包含声明。
由于 CSSMediaRule
可以包含嵌套规则(可通过其 cssRules
属性访问),因此声明会自动封装在 CSSStyleRule
中。
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(.foo)"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 1) =
- background-color: red
作者:terry,如若转载,请注明出处:https://www.web176.com/news/frontend/28513.html