1. 引言
本节非规范性。
这个模块描述了在一个样式规则内嵌套另一个样式规则的支持, 允许内部规则的选择器引用外部规则所匹配的元素。 该特性允许将相关样式聚合到 CSS 文档中的单一结构内, 提高可读性和可维护性。
测试
嵌套的一般测试
- block-skipping.html (实时测试) (源代码)
- delete-other-rule-crash.html (实时 测试) (源代码)
- double-parent-pseudo-in-placeholder-crash.html (实时 测试) (源代码)
- has-nesting.html (实时测试) (源代码)
- invalidation-001.html (实时测试) (源代码)
- invalidation-002.html (实时测试) (源代码)
- invalidation-003.html (实时测试) (源代码)
- invalidation-004.html (实时测试) (源代码)
- nested-error-recovery.html (实时 测试) (源代码)
- nesting-basic.html (实时测试) (源代码)
- nesting-revert-rule.tentative.html (实时 测试) (源代码)
- parent-pseudo-in-placeholder-crash.html (实时 测试) (源代码)
- pseudo-part-crash.html (实时测试) (源代码)
- pseudo-where-crash.html (实时测试) (源代码)
- supports-is-consistent.html (实时 测试) (源代码)
1.1. 模块交互
该模块引入了扩展 [CSS21] 解析模型的新解析规则。 它引入了扩展 [SELECTORS-4] 模块的选择器。 它扩展并修改了在 [CSSOM-1] 模块中定义的一些 IDL 和算法。
1.2. 值
本规范未定义任何新的属性或值。
2. 说明
本节非规范性。
设想你有一些想以更紧凑的方式编写的 CSS。
.foo{ color : green; } .foo .bar{ font-size : 1.4 rem ; }
使用嵌套(Nesting),你可以这样写:
.foo{ color : green; .bar{ font-size : 1.4 rem ; } }
如果你在 Sass 或其他 CSS 预处理器中做过样式嵌套,你会觉得这非常熟悉。
你可以在父样式规则内嵌套任何规则:
main{ div{ ...} .bar{ ...} #baz{ ...} :has ( p) { ...} ::backdrop{ ...} [ lang|="zh" ] { ...} *{ ...} }
默认情况下,子规则的选择器被假定通过后代组合符连接到父规则,但你可以用任何组合符开始嵌套选择器以改变该行为:
main{ + article{ ...} > p{ ...} ~ main{ ...} }
新的 & 选择器让你显式引用父选择器所匹配的元素,因此之前的示例可以写成:
main{ & + article{ ...} & > p{ ...} & ~ main{ ...} }
但你也可以将 & 放在嵌套选择器的其他位置, 以指示父规则和子规则之间的其他类型的关系。 例如,下面的 CSS:
ul{ padding-left : 1 em ; } .component ul{ padding-left : 0 ; }
可以用嵌套重写为:
ul{ padding-left : 1 em ; .component &{ padding-left : 0 ; } }
同样,& 为你提供了一种方式来表示“这是我希望嵌套选择器放置的位置”。
当你不希望选择器之间有空格时它也很有用。例如:
a{ color : blue; &:hover{ color : lightblue; } }
这样的代码产生与 相同的结果。
如果没有 &,
你会得到 ——注意 a 与 :hover 之间的空格——这会导致无法为你的悬停链接设置样式。
你可以嵌套多层——在已嵌套的 CSS 内再次嵌套——任意层级。 你可以将嵌套与容器查询、支持查询、媒体查询和/或层叠层混合使用, 几乎任何东西都可以放在任何东西里面。
3. 嵌套样式规则
样式规则可以嵌套在其他样式规则内。 这些 嵌套样式规则 完全像普通样式规则一样——通过选择器将属性关联到元素——但它们“继承”其父规则的选择器上下文, 允许它们在不重复父选择器的情况下进一步构建父选择器, 并且可以多次这么做。
一个 嵌套样式规则 与普通样式规则完全相同, 不同之处在于它可以使用 相对选择器, 这些相对选择器隐式相对于父规则所匹配的元素。
测试
.foo{ color : red; a{ color : blue; } }
是有效的, 并且等价于:
.foo{ color : red; } .foo a{ color : blue; }
嵌套规则也可以使用 嵌套选择器 直接引用父规则所匹配的元素, 或使用 相对选择器 语法来指定除“后代”之外的关系。
.foo{ color : red; &:hover{ color : blue; } } /* 等价于: */ .foo{ color : red; } .foo:hover{ color : blue; }
.foo{ color : red; + .bar{ color : blue; } } /* 等价于: */ .foo{ color : red; } .foo + .bar{ color : blue; }
3.1. 语法
样式规则的内容现在接受 样式规则 中的 嵌套样式规则 和 at 规则, 以及现有的 声明。
嵌套样式规则 与非嵌套规则的不同之处如下:
-
一个 嵌套样式规则 接受一个 <relative-selector-list> 作为其前导(而不仅仅是一个 <selector-list>)。 任何 相对选择器 都相对于由 嵌套选择器 表示的元素。
-
如果 <relative-selector-list> 中的某个选择器未以组合符开始但包含 嵌套选择器, 则将其解释为非 相对选择器。
嵌套样式规则的精确解析细节定义在 [CSS-SYNTAX-3] 中。
无效的 嵌套样式规则 会被忽略, 其内容亦会被忽略, 但不会使其父规则无效。
包含 相对选择器 的嵌套规则会包含其隐含 嵌套选择器 的特异性。 例如,.foo { > .bar {...}} 与 .foo { & > .bar {...}} 的内部规则具有相同的特异性。
例如,如果一个组件使用类 .foo, 而嵌套组件使用 .fooBar, 在 Sass 中你可以这样写:
.foo{ color : blue; &Bar{ color : red; } } /* 在 Sass 中,这等价于 */ .foo { color: blue; } .fooBar { color: red; } */
这在 CSS 中是不允许的, 因为嵌套不是语法转换, 而是匹配父选择器实际匹配的元素。
同样,选择器 &Bar 在 CSS 中本身就是无效的, 因为 Bar 部分是一个类型选择器, 必须出现在复合选择器的开头。 (也就是说,它必须写作 Bar&。) 所以,幸运的是,CSS 嵌套与预处理器语法之间并不存在重叠。
注: 这样明确表述是为了捕获像 :is(:unknown(&), .bar) 的情况, 其中一个未知的选择器 (由于未知,我们无法知道其参数是否打算被解析为选择器) 是选择器中唯一包含 & 的部分。 由于该部分可能是只有新版本浏览器支持的有效选择器, 我们不希望解析依赖于无关的版本问题, 因此我们仍然将其视为 包含嵌套选择器。
If a <forgiving-selector-list> has an item that 包含嵌套选择器 but is invalid, that item is preserved exactly as-is rather than being discarded. (This does not change the matching behavior of the selector—an invalid selector still fails to match anything—just the serialization of the selector.)
上面那段在我们把 & 本身移动到选择器模块时需要移到“选择器”部分; 我在这里为方便做了临时修补。
3.2. 示例
/* & 可以单独使用 */ .foo{ color : blue; & > .bar{ color : red; } > .baz{ color : green; } } /* 等价于 .foo { color: blue; } .foo > .bar { color: red; } .foo > .baz { color: green; } */ /* 或者在复合选择器中, 精化父选择器 */ .foo{ color : blue; &.bar{ color : red; } } /* 等价于 .foo { color: blue; } .foo.bar { color: red; } */ /* 列表中的多个选择器都相对于父选择器 */ .foo, .bar{ color : blue; + .baz, &.qux{ color : red; } } /* 等价于 .foo, .bar { color: blue; } :is(.foo, .bar) + .baz, :is(.foo, .bar).qux { color: red; } */ /* & 可以在单个选择器中使用多次 */ .foo{ color : blue; & .bar & .baz & .qux{ color : red; } } /* 等价于 .foo { color: blue; } .foo .bar .foo .baz .foo .qux { color: red; } */ /* & 不必位于选择器的开头 */ .foo{ color : red; .parent &{ color : blue; } } /* 等价于 .foo { color: red; } .parent .foo { color: blue; } */ .foo{ color : red; :not ( &) { color : blue; } } /* 等价于 .foo { color: red; } :not(.foo) { color: blue; } */ /* 但是如果你使用相对选择器, 会自动隐含一个初始的 & */ .foo{ color : red; + .bar + &{ color : blue; } } /* 等价于 .foo { color: red; } .foo + .bar + .foo { color: blue; } */ /* 有点荒谬,但 & 也可以单独使用。 */ .foo{ color : blue; &{ padding : 2 ch ; } } /* 等价于 .foo { color: blue; } .foo { padding: 2ch; } // 或者 .foo { color: blue; padding: 2ch; } */ /* 再次说明,虽然荒谬,但可以重复使用。 */ .foo{ color : blue; &&{ padding : 2 ch ; } } /* 等价于 .foo { color: blue; } .foo.foo { padding: 2ch; } */ /* 父选择器可以任意复杂 */ .error, #404{ &:hover > .baz{ color : red; } } /* 等价于 :is(.error, #404):hover > .baz { color: red; } */ .ancestor .el{ .other-ancestor &{ color : red; } } /* 等价于 .other-ancestor :is(.ancestor .el) { color: red; } /* 嵌套选择器本身也可以很复杂 */ .foo{ &:is ( .bar, &.baz) { color : red; } } /* 等价于 .foo :is(.bar, .foo.baz) { color: red; } */ /* 多层嵌套会“叠加”选择器 */ figure{ margin : 0 ; > figcaption{ background : hsl ( 0 0 % 0 % /50 % ); > p{ font-size : .9 rem ; } } } /* 等价于 figure { margin: 0; } figure > figcaption { background: hsl(0 0% 0% / 50%); } figure > figcaption > p { font-size: .9rem; } */ /* 与层叠层(Cascade Layers)一起使用的示例 */ @layer base{ html{ block-size : 100 % ; body{ min-block-size : 100 % ; } } } /* 等价于 @layer base { html { block-size: 100%; } html body { min-block-size: 100%; } } */ /* 嵌套层叠层的示例 */ @layer base{ html{ block-size : 100 % ; @layer support{ body{ min-block-size : 100 % ; } } } } /* 等价于 @layer base { html { block-size: 100%; } } @layer base.support { html body { min-block-size: 100%; } } */ /* 与作用域(Scoping)一起使用的示例 */ @scope ( .card) to( > header) { :scope{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; > header{ border-block-end : 1 px solid white; } } } /* 等价于 @scope (.card) to (> header) { :scope { inline-size: 40ch; aspect-ratio: 3/4; } :scope > header { border-block-end: 1px solid white; } } */ /* 嵌套作用域的示例 */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; @scope ( &) to( > header > *) { :scope > header{ border-block-end : 1 px solid white; } } } /* 等价于 .card { inline-size: 40ch; aspect-ratio: 3/4; } @scope (.card) to (> header > *) { :scope > header { border-block-end: 1px solid white; } } */
3.3. 嵌套其他 at 规则
除了 嵌套样式规则, 本规范还允许在 样式规则 内放置 嵌套组规则:任何其主体包含 样式规则 的 at 规则也可以嵌套在一个 样式规则 内,除非另有说明。
以这种方式嵌套时, 嵌套组规则 块的内容 按照 <block-contents> 进行解析,而不是 <rule-list>:
测试
此类 嵌套组规则 的含义和行为在其他方面保持不变, 除非另有说明。
/* 属性可以直接使用 */ .foo{ display : grid; @media ( orientation: landscape) { grid-auto-flow : column; } } /* 等价于: */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column} } /* 并且也等价于未嵌套的: */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column; } } /* 条件可以进一步嵌套 */ .foo{ display : grid; @media ( orientation: landscape) { grid-auto-flow : column; @media ( min-width >1024 px ) { max-inline-size : 1024 px ; } } } /* 等价于 */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column; } } @media ( orientation: landscape) and( min-width >1024 px ) { .foo{ max-inline-size : 1024 px ; } } /* 嵌套层叠层示例 */ html{ @layer base{ block-size : 100 % ; @layer support{ & body{ min-block-size : 100 % ; } } } } /* 等价于 */ @layer base{ html{ block-size : 100 % ; } } @layer base.support{ html body{ min-block-size : 100 % ; } } /* 嵌套作用域示例 */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; @scope ( &) { :scope{ border : 1 px solid white; } } } /* 等价于 */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; } @scope ( .card) { :scope{ border-block-end : 1 px solid white; } }
连续的直接嵌套属性序列会被自动封装到 嵌套声明规则 中。 (这在 CSSOM 中是可观察到的。)
3.3.1. 嵌套 @scope 规则
当 @scope 规则是一个 嵌套组规则 时, 在 <scope-start> 选择器中的 & 指代最近的祖先样式规则所匹配的元素。
.parent{ color : blue; @scope ( & > .scope) to( & .limit) { & .content{ color : red; } } }
等价于:
.parent{ color : blue; } @scope ( .parent > .scope) to( :where ( :scope) .limit) { :where ( :scope) .content{ color : red; } }
3.4. 混合嵌套规则和声明
当一个样式规则既包含声明 又包含 嵌套样式规则 或 嵌套组规则 时, 三者可以任意混合。 出现在规则之后或规则之间的声明 会被隐式地包裹在 嵌套声明规则 中, 以保留它们相对于其他规则的顺序。
article{ color : green; &{ color : blue; } color: red; } /* 等价于 */ article{ color : green; } :is ( article) { color : blue; } article{ color : red; } /* 不等价于 */ article{ color : green; } article{ color : red; } :is ( article) { color : blue; }
为确定 出现顺序(Order Of Appearance) 的目的, 嵌套 样式规则 和 嵌套组规则 被视为在其父规则之后出现。
article{ color : blue; &{ color : red; } }
两个声明具有相同的特异性 (0,0,1), 但是嵌套规则被视为在其父规则之后出现, 因此 color: red 声明在级联中胜出。
另一方面,在此示例中:
article{ color : blue; :where ( &) { color : red; } }
在 :where() 伪类会将 嵌套选择器 的特异性降为 0, 因此 color: red 声明现在的特异性为 (0,0,0), 在“出现顺序”被考虑之前就输给了 color: blue 声明。
注: 虽然可以自由地混合声明和嵌套规则, 但这样做会更难阅读并且有些令人困惑, 因为后面的属性会被自动包裹在源文本中并未出现的 嵌套声明规则 中。 为了可读性,建议作者在样式规则中先把所有属性放在前面, 然后再放任何嵌套规则。 (这对较旧的用户代理也稍好一些:由于解析和错误恢复的具体细节, 出现在嵌套规则之后的属性可能会被跳过。)
4. 嵌套选择器:& 选择器
当在 嵌套样式规则 中使用时, 必须能够引用父规则所匹配的元素; 说到底,这正是嵌套的全部意义。 为此,本规范定义了一个新的选择器, 即嵌套选择器, 用法为 & (U+0026 AMPERSAND)。
当在嵌套样式规则的选择器中使用时, 嵌套选择器 表示父规则所匹配的元素。 在任何其他上下文中使用时, 它在该上下文中表示与 :scope 相同的元素 (除非另有定义)。
a, b{ & c{ color : blue; } }
等价于
:is ( a, b) c{ color : blue; }
嵌套选择器 不能表示伪元素 (与 :is() 伪类的行为相同)。
.foo, .foo::before, .foo::after{ color : red; &:hover{ color : blue; } }
其中的 & 只表示由 .foo 匹配的元素; 换言之,它等价于:
.foo, .foo::before, .foo::after{ color : red; } .foo:hover{ color : blue; }
我们希望放宽此限制, 但需要同时为 :is() 和 & 一并进行修改, 因为它们是基于相同的底层机制构建的。 (Issue 7433)
嵌套选择器 的特异性等于父样式规则选择器列表中各个复杂选择器的最大特异性 (与 :is() 的行为相同), 如果不存在这样的选择器列表则为零。
#a, b{ & c{ color : blue; } } .foo c{ color : red; }
那么在如下 DOM 结构中
< b class = foo > < c > Blue text</ c > </ b >
文本将呈蓝色,而不是红色。 & 的特异性是 #a([1,0,0])和 b([0,0,1]) 中较大的一个, 因此为 [1,0,0], 整个 & c 选择器的特异性为 [1,0,1], 大于 .foo c 的特异性 [0,1,1]。
值得注意的是,这与将嵌套手动展开为非嵌套规则得到的结果不同, 因为在手动展开的情况下,color: blue 声明会由 b c 选择器匹配([0,0,2]), 而不是由 #a c([1,0,1])匹配。
为什么特异性会与非嵌套规则不同?
嵌套选择器 有意采用与 :is() 相同的特异性规则, 即使用其参数中最大的特异性, 而不是跟踪究竟哪一个选择器实际匹配。
这是出于性能原因的必要选择; 如果一个选择器的特异性取决于具体匹配到的方式而有多个可能值, 会使选择器匹配变得非常复杂且更慢。
但这仍未解答根本问题: 为什么我们用 & 基于 :is() 来定义? 一些非浏览器的嵌套类功能实现并不把嵌套解糖为 :is(), 主要因为它们出现在 :is() 出现之前。 它们改为直接展开; 但是这带来了严重的问题, 因为某些(相当常见的)情况会意外地产生巨量的选择器,出现指数级爆炸。
.a1, .a2, .a3{ .b1, .b2, .b3{ .c1, .c2, .c3{ ...; } } } /* 朴素地解糖为 */ .a1 .b1 .c1, .a1 .b1 .c2, .a1 .b1 .c3, .a1 .b2 .c1, .a1 .b2 .c2, .a1 .b2 .c3, .a1 .b3 .c1, .a1 .b3 .c2, .a1 .b3 .c3, .a2 .b1 .c1, .a2 .b1 .c2, .a2 .b1 .c3, .a2 .b2 .c1, .a2 .b2 .c2, .a2 .b2 .c3, .a2 .b3 .c1, .a2 .b3 .c2, .a2 .b3 .c3, .a3 .b1 .c1, .a3 .b1 .c2, .a3 .b1 .c3, .a3 .b2 .c1, .a3 .b2 .c2, .a3 .b2 .c3, .a3 .b3 .c1, .a3 .b3 .c2, .a3 .b3 .c3{ ...}
这里,三层嵌套, 每层列表中各有三个选择器, 会生成 27 个解糖后的选择器。 向列表中添加更多选择器、增加嵌套层数或使嵌套规则更复杂, 都会使一个相对较小的规则扩展为数兆字节的选择器(或更多!)。
一些 CSS 工具通过启发式丢弃某些变体来避免最坏情况, 因此它们并不需要输出那么多,但仍然可能是正确的, 而这是用户代理无法采用的选项。
使用 :is() 进行解糖可以完全消除这个问题, 代价是使特异性略微变得不那么有用, 经评估这是一个合理的权衡。
嵌套选择器 能够匹配父规则所匹配的那些无特征(featureless) 元素。
虽然在复合选择器中 嵌套选择器 的位置不会改变其行为 (即 &.foo 与 .foo& 匹配相同元素), 现有规则仍然适用:如果存在类型选择器,它必须出现在复合选择器的最前面 (即 &div 是非法的,必须写成 div&)。
测试
- contextually-invalid-selectors-001.html (live test) (source)
- contextually-invalid-selectors-002.html (live test) (source)
- contextually-invalid-selectors-003.html (live test) (source)
- host-nesting-001.html (live test) (source)
- host-nesting-002.html (live test) (source)
- host-nesting-003.html (live test) (source)
- host-nesting-004.html (live test) (source)
- host-nesting-005.html (live test) (source)
- nesting-type-selector.html (live test) (source)
5. 嵌套声明规则
出于一些技术性原因, 将样式规则开头出现的属性与穿插在其他规则中的属性区分开来是很重要的。
.foo{ color : red; @media ( ...) { ...} background: blue; }
我们需要对 color: red
和 background: blue 做稍微不同的处理。
特别地,在 CSSOM 中,
color: red 会作为样式规则的 style
属性暴露出来,
而 background: blue 则需要显示在它的 cssRules
列表中。
为此,CSS 解析会自动将此类属性包裹在一个特殊的子规则中以包含它们。 然而,如果我们将它们包裹在带有 样式规则 并使用 & 选择器的规则中, 会出现一些不太理想的行为:
.foo, .foo::before{ color : red; &{ background : blue; } }
嵌套规则不会将 background 属性应用到 .foo::before 元素, 因为 & 无法表示伪元素。
类似地,嵌套在非样式规则中的子声明需要以某种方式作为 规则 在外部暴露,
因为此类规则(如 @media)从未拥有过 style
属性。
这些问题与上面相同。
为了解决所有这些问题, 我们改为将连续的直接嵌套属性序列包裹在一个 嵌套声明规则 中。
除非另有说明, 嵌套声明规则 是一个 嵌套样式规则, 并且在行为上与任何其他样式规则完全相同。 它匹配与其父样式规则完全相同的元素和伪元素, 具有相同的特异性行为。(这在某种程度上类似于使用带有 & 选择器的样式规则,但更加强大,如上所述。)
为什么存在 嵌套声明规则?
最初,本规范将样式规则中的所有声明分组在一起, 将它们“移动”到规则的开头处来处理。 它还自动将嵌套组规则内的原始声明包装到普通的样式规则中, 使用 & 选择器。
我们改为使用 嵌套声明规则 的原因有两点。
首先,使用 & {...} 规则来隐式地将声明包装在一个 嵌套组规则 中会改变行为。 如本注释后面的示例所示, 它会破坏父样式规则包含伪元素的情况, 即使在不包含伪元素的情况下, 它也可能改变嵌套声明的特异性行为。 切换到使用 嵌套声明规则 可以避免这些问题, 使嵌套的 @media/等的行为与*非*嵌套的 @media/等一致。
其次,未来的某些 CSS 特性(尤其是“混入”)的细节如果将交错的声明自动移动到样式规则的开头将无法正确工作。 我们需要保持它们与其他规则的相对顺序, 为了能在 CSSOM 中表示这一点, 必须将它们包装在某种规则中。 如果只是使用普通的 & {...} 规则,同样会出现前述问题, 因此 嵌套声明规则 允许我们在不产生副作用的情况下实现这一点。
.foo, .foo::before, .foo::after{ color : black; @media ( prefers-color-scheme: dark) { &{ color : white; } } }
在暗色模式页面中, .foo 元素的文本颜色会变为白色, 但其 ::before 和 ::after 伪元素将保持黑色, 因为 & 选择器无法表示伪元素。
但是,如果改为这样书写:
.foo, .foo::before, .foo::after{ color : black; @media ( prefers-color-scheme: dark) { color : white; } }
那么 color: white 会被隐式地包裹在一个 嵌套声明规则 中, 保证与其父样式规则完全相同地匹配, 因此元素及其伪元素在暗色模式页面中都会变为白色文本。
.foo{ color : black; @media ( ...) { ...} background: silver; }
如果检查 .foo 规则的 CSSOM 对象,
其 style
属性将只包含一个声明:
即 color: black。
background: silver 声明
将出现在隐式创建的 嵌套声明子规则 中,
在 fooRule
可找到它。
测试
- mixed-declarations-rules.html (visual test) (source)
- nested-declarations-cssom-whitespace.html (live test) (source)
- nested-declarations-cssom.html (live test) (source)
- nested-declarations-matching.html (live test) (source)
6. CSSOM
注: [CSSOM-1] 现在定义
CSSStyleRule
可以拥有子规则。
当在序列化一个 相对选择器(出现在 嵌套样式规则 中)时, 必须将该选择器绝对化, 并插入隐含的 嵌套选择器。
6.1. The CSSNestedDeclarations
Interface
The CSSNestedDeclarations
interface 表示一个 嵌套声明规则。
[Exposed =Window ]interface :CSSNestedDeclarations CSSRule { [SameObject ,PutForwards =cssText ]readonly attribute CSSStyleProperties style ; };
style 属性
必须返回该规则的 CSSStyleProperties
对象,且具有以下属性:
- computed flag
-
未设置
- readonly flag
-
未设置
- declarations
-
规则中声明的声明,按指定顺序排列。
- parent CSS rule
- owner node
-
Null
The CSSNestedDeclarations
规则的序列化行为如同其声明块已被直接序列化一般。
注: 这意味着多个相邻的 嵌套声明规则(例如通过 insertRule
创建)
在序列化并重新解析后会合并为单个规则。
隐私考虑
本规范未报告任何新的隐私考虑。
安全性考虑
本规范未报告任何新的安全性考虑。
7. 变更
自 2023-02-14 工作草案 以来的重大变更:
-
<scope-start> 选择器在 @scope 规则中不再作为嵌套的父规则。 (Issue 9740)
-
澄清了 嵌套选择器 允许匹配无特征元素的情况。
-
将 &div 改回为无效; 由于语法现在支持“无限前瞻”,我们不再需要允许它。 此外,这样做可以避免与预处理器的冲突。 (Issue 8662)
-
CSSOM 现在定义 CSSStyleRule 为 CSSGroupingRule 的子类, 因此手动定义的
cssRules属性及相关机制已被移除。 (Issue 8940) -
澄清了隐含的嵌套选择器对特异性的影响。 (Issue 9069)
-
与规则交错的声明(或嵌套组规则中的所有声明)现在会自动封装在
规则中。 (同时添加了@nest 规则。) (Issue 8738)@nest -
用 嵌套声明规则 替换了
。 (Issue 10234)@nest -
增加了 Web 平台测试覆盖。