CSS 嵌套模块第 1 级

W3C 工作草案

关于此文档的更多细节
此版本
https://w3org.cn/TR/2026/WD-css-nesting-1-20260122/
最新发布版本
https://w3org.cn/TR/css-nesting-1/
编辑草案
https://drafts.csswg.org/css-nesting/
历史
https://w3org.cn/standards/history/css-nesting-1/
反馈
CSS 工作组问题仓库
文档内联
编辑
Tab Atkins-Bittner (Google)
前任编辑
Adam Argyle (Google)
建议编辑此规范
GitHub 编辑器
测试套件
https://wpt.fyi/results/css/css-nesting/

摘要

本模块引入了在一个样式规则内部嵌套另一个样式规则的能力,子规则的选择器相对于父规则的选择器。这样可以提升 CSS 样式表的模块化和可维护性。

CSS 是一种用于描述结构化文档(如 HTML 和 XML)在屏幕、纸张等介质上渲染方式的语言。

关于本文档

本节描述了本文件发布时的状态。当前 W3C 出版物列表及本技术报告的最新修订版可在 W3C 标准和草案索引中找到。

本文件由 CSS 工作组推荐标准轨道发布为工作草案。发布为工作草案并不意味着 W3C 及其成员的认可。

这是一个草案文档,可能随时会被其他文档更新、替换或废弃。将其作为进展中的工作之外的任何内容进行引用是不恰当的。

请通过 在 GitHub 上提交 issue(首选),在标题中加上规范代码 “css-nesting”,例如:“[css-nesting] …评论摘要…”。所有 issue 和评论均已归档。或者,也可以将反馈发送至已归档的公共邮件列表 www-style@w3.org

本文件受 2025 年 8 月 18 日 W3C 流程文件的管辖。

本文档由在一个受 W3C 专利政策约束下运作的组织制作。W3C 维护着一份与该组织交付成果相关的专利披露公开列表;该页面还包含了披露专利的说明。任何个人如果确实获知其认为包含必要权利要求 (Essential Claim) 的专利,必须根据 W3C 专利政策第 6 节披露该信息。

1. 简介

本节不具有规范性。

本模块描述了在一个样式规则内部嵌套另一个样式规则的支持,允许内部规则的选择器引用外层规则匹配的元素。此功能可以把相关的样式聚合到 CSS 文档的同一结构中,从而提升可读性和可维护性。

测试

嵌套的一般测试


1.1. 模块交互

本模块引入了扩展 [CSS21] 解析模型的新解析规则。它引入了扩展 [SELECTORS-4] 模块的选择器。它也扩展并修改了 [CSSOM-1] 模块中定义的部分 IDL 与算法。

1.2.

本规范未定义任何新属性或新取值。

2. 说明

本节是非规范性的。

想象一下你有一些 CSS,希望以更紧凑的方式编写。

.foo {
  color: green;
}
.foo .bar {
  font-size: 1.4rem;
}

使用嵌套,你可以这么写代码:

.foo {
  color: green;
  .bar {
    font-size: 1.4rem;
  }
}

如果你以前在 Sass 或其它 CSS 预处理器中进行过嵌套样式,你会觉得这非常熟悉。

你可以在父样式规则内部嵌套任意规则。

main {
  div { ... }
  .bar { ... }
  #baz { ...}
  :has(p) { ... }
  ::backdrop { ... }
  [lang|="zh"] { ... }
  * { ... }
}

默认情况下,子规则的选择器被视为通过后代组合符与父规则相连,但你可以在嵌套选择器前添加任意组合符来改变这一点。

main {
  + article { ... }
  > p { ... }
  ~ main { ... }
}

新的 & 选择器允许你显式引用父选择器匹配的元素,因此上述例子也可以写成:

main {
  & + article { ... }
  & > p { ... }
  & ~ main { ... }
}

但你也可以把 & 放在嵌套选择器的其他位置,以表示父子规则之间的其他关系类型。例如,下面这段 CSS:

ul {
  padding-left: 1em;
}
.component ul {
  padding-left: 0;
}

可以使用嵌套改写为:

ul {
  padding-left: 1em;
  .component & {
    padding-left: 0;
  }
}

同样,& 为你提供了一种“这就是我想让嵌套选择器出现的位置”的表达方式。

当你不想在选择器之间留空格时,它也非常有用。例如:

a {
  color: blue;
  &:hover {
    color: lightblue;
  }
}

这段代码的效果等同于 a:hover {。如果没有 &,则会得到 a :hover {——注意 a:hover 之间的空格——这会导致悬停链接样式失效。

你可以嵌套多层——在已经嵌套的 CSS 里再嵌套 CSS——层数不设上限。你可以随意将嵌套与容器查询、Supports 查询、媒体查询以及/或层叠层混合使用。(几乎)任何东西都可以放在任何东西内部。

3. 嵌套样式规则

样式规则可以嵌套在其他样式规则内部。这些 嵌套样式规则 的行为与普通样式规则完全相同——通过选择器将属性关联到元素——但是它们“继承”父规则的选择器上下文,允许在不重复(甚至多次重复)父选择器的情况下进一步构建选择器。

一个 嵌套样式规则 与普通样式规则相同,只是它可以使用 相对选择器,这些相对选择器隐式地相对于父规则匹配的元素。

测试
也就是说,像下面这样的嵌套样式规则:
.foo {
  color: red;

  a {
    color: blue;
  }
}

是合法的,并且等价于:

.foo {
  color: red;
}
.foo a {
  color: blue;
}

嵌套规则也可以使用 嵌套选择器 直接引用父规则匹配的元素,或使用 相对选择器 语法来指定除“后代”之外的其他关系。

.foo {
  color: red;

  &:hover {
    color: blue;
  }
}

/* equivalent to: */

.foo { color: red; }
.foo:hover { color: blue; }
.foo {
  color: red;

  + .bar {
    color: blue;
  }
}

/* equivalent to: */

.foo { color: red; }
.foo + .bar { color: blue; }
测试

3.1. 语法

样式规则的内容现在接受 嵌套样式规则at‑rule,以及现有的 声明

嵌套样式规则 与非嵌套规则在以下方面不同:

嵌套样式规则的具体解析细节定义于 [CSS‑SYNTAX‑3]

无效的 嵌套样式规则 将被忽略,其内容也一起被忽略,但不会导致其父规则失效。

包含 相对选择器 的嵌套规则会把它们暗含的 嵌套选择器 的特异性计入。例如,.foo { > .bar {...}}.foo { & > .bar {...}} 对其内部规则的特异性是相同的。

一些会在预处理阶段将嵌套转换为字符串拼接的 CSS 生成工具,会让作者构造出跨层级的单一 简单选择器。在使用 BEM 等层级命名模式时,这可以减少文件内部的重复。

例如,若一个组件使用类 .foo,而一个嵌套组件使用 .fooBar,在 Sass 中可以这样写:

.foo {
  color: blue;
  &Bar { color: red; }
}
/* In Sass, this is equivalent to
  .foo { color: blue; }
  .fooBar { color: red; }
*/

这在 CSS 中是不允许的,因为嵌套并不是一种语法转换,而是直接匹配父选择器匹配到的实际元素。

同样,选择器 &Bar 在 CSS 中本身就是非法的,因为 Bar 部分是类型选择器,必须位于复合选择器的最前面(即应写作 Bar&)。所以幸运的是,CSS Nesting 与预处理器语法之间不存在冲突。

如果当选择器在解析为任意类型的选择器时,遇到值为 “&” (U+0026 AMPERSAND) 的<delim-token>,则称该选择器 包含嵌套选择器

注意:此表述方式是为了捕获诸如 :is(:unknown(&), .bar) 这类情形——其中的未知选择器(因为未知,我们无法确定参数是否应该被解析为选择器)是唯一包含 & 的部分。由于这可能是只有新浏览器才支持的完全合法选择器,而我们不希望解析行为受无关版本问题的影响,故仍将其视为包含嵌套选择器

如果<forgiving-selector-list>中的某个项包含嵌套选择器但本身无效,则该项会原样保留而不是被丢弃。(这不会改变选择器的匹配行为——无效选择器仍然匹配不到任何元素——但会影响选择器的序列化方式。)

测试

前面的段落需要在我们把 & 本身迁移到 Selectors 模块时一起迁移;这里的写法是为方便而做的临时补丁。

3.2. 示例

/* & can be used on its own */
.foo {
  color: blue;
  & > .bar { color: red; }
  > .baz { color: green; }
}
/* equivalent to
  .foo { color: blue; }
  .foo > .bar { color: red; }
  .foo > .baz { color: green; }
*/


/* or in a compound selector,
   refining the parent’s selector */
.foo {
  color: blue;
  &.bar { color: red; }
}
/* equivalent to
  .foo { color: blue; }
  .foo.bar { color: red; }
*/

/* multiple selectors in the list are all
   relative to the parent */
.foo, .bar {
  color: blue;
  + .baz, &.qux { color: red; }
}
/* equivalent to
  .foo, .bar { color: blue; }
  :is(.foo, .bar) + .baz,
  :is(.foo, .bar).qux { color: red; }
*/

/* & can be used multiple times in a single selector */
.foo {
  color: blue;
  & .bar & .baz & .qux { color: red; }
}
/* equivalent to
  .foo { color: blue; }
  .foo .bar .foo .baz .foo .qux { color: red; }
*/

/* & doesn’t have to be at the beginning of the selector */

.foo {
  color: red;
  .parent & {
    color: blue;
  }
}
/* equivalent to
  .foo { color: red; }
  .parent .foo { color: blue; }
*/

.foo {
  color: red;
  :not(&) {
    color: blue;
  }
}
/* equivalent to
  .foo { color: red; }
  :not(.foo) { color: blue; }
*/

/* But if you use a relative selector,
  an initial & is implied automatically */

.foo {
  color: red;
  + .bar + & { color: blue; }
}

/* equivalent to
  .foo { color: red; }
  .foo + .bar + .foo { color: blue; }
*/

/* Somewhat silly, but & can be used all on its own, as well. */
.foo {
  color: blue;
  & { padding: 2ch; }
}
/* equivalent to
  .foo { color: blue; }
  .foo { padding: 2ch; }

  // or

  .foo {
    color: blue;
    padding: 2ch;
  }
*/

/* Again, silly, but can even be doubled up. */
.foo {
  color: blue;
  && { padding: 2ch; }
}
/* equivalent to
  .foo { color: blue; }
  .foo.foo { padding: 2ch; }
*/

/* The parent selector can be arbitrarily complicated */
.error, #404 {
  &:hover > .baz { color: red; }
}
/* equivalent to
  :is(.error, #404):hover > .baz { color: red; }
*/

.ancestor .el {
  .other-ancestor & { color: red; }
}
/* equivalent to
  .other-ancestor :is(.ancestor .el) { color: red; }

/* As can the nested selector */
.foo {
  & :is(.bar, &.baz) { color: red; }
}
/* equivalent to
  .foo :is(.bar, .foo.baz) { color: red; }
*/

/* Multiple levels of nesting "stack up" the selectors */
figure {
  margin: 0;

  > figcaption {
    background: hsl(0 0% 0% / 50%);

    > p {
      font-size: .9rem;
    }
  }
}
/* equivalent to
  figure { margin: 0; }
  figure > figcaption { background: hsl(0 0% 0% / 50%); }
  figure > figcaption > p { font-size: .9rem; }
*/

/* Example usage with Cascade Layers */
@layer base {
  html {
    block-size: 100%;

    body {
      min-block-size: 100%;
    }
  }
}
/* equivalent to
  @layer base {
    html { block-size: 100%; }
    html body { min-block-size: 100%; }
  }
*/

/* Example nesting Cascade Layers */
@layer base {
  html {
    block-size: 100%;

    @layer support {
      body {
        min-block-size: 100%;
      }
    }
  }
}
/* equivalent to
  @layer base {
    html { block-size: 100%; }
  }
  @layer base.support {
    html body { min-block-size: 100%; }
  }
*/

/* Example usage with Scoping */
@scope (.card) to (> header) {
  :scope {
    inline-size: 40ch;
    aspect-ratio: 3/4;

    > header {
      border-block-end: 1px solid white;
    }
  }
}
/* equivalent to
  @scope (.card) to (> header) {
    :scope { inline-size: 40ch; aspect-ratio: 3/4; }
    :scope > header { border-block-end: 1px solid white; }
  }
*/

/* Example nesting Scoping */
.card {
  inline-size: 40ch;
  aspect-ratio: 3/4;

  @scope (&) to (> header > *) {
    :scope > header {
      border-block-end: 1px solid white;
    }
  }
}

/* equivalent to
  .card { inline-size: 40ch; aspect-ratio: 3/4; }
  @scope (.card) to (> header > *) {
    :scope > header { border-block-end: 1px solid white; }
  }
*/

3.3. 嵌套其他 At-规则

除了嵌套样式规则之外,本规范还允许在样式规则内部嵌套嵌套组规则:任何其主体包含样式规则的 at‑rule 均可以嵌套在样式规则内部,除非另有规定。

以这种方式嵌套时,嵌套组规则块的内容会被解析为 <block-contents>,而不是 <rule-list>

具体而言,这些规则能够成为嵌套组规则
测试

此类嵌套组规则的含义与行为保持不变,除非另有规定。

例如,以下条件嵌套是合法的:
/* Properties can be directly used */
.foo {
  display: grid;

  @media (orientation: landscape) {
    grid-auto-flow: column;
  }
}

/* equivalent to: */
.foo {
  display: grid;
}
@media (orientation: landscape) {
  .foo {
    grid-auto-flow: column
  }
}

/* and also equivalent to the unnested: */
.foo { display: grid; }

@media (orientation: landscape) {
  .foo {
    grid-auto-flow: column;
  }
}

/* Conditionals can be further nested */
.foo {
  display: grid;

  @media (orientation: landscape) {
    grid-auto-flow: column;

    @media (min-width > 1024px) {
      max-inline-size: 1024px;
    }
  }
}

/* equivalent to */
.foo { display: grid; }

@media (orientation: landscape) {
  .foo {
    grid-auto-flow: column;
  }
}

@media (orientation: landscape) and (min-width > 1024px) {
  .foo {
    max-inline-size: 1024px;
  }
}

/* Example nesting Cascade Layers */
html {
  @layer base {
    block-size: 100%;

    @layer support {
      & body {
        min-block-size: 100%;
      }
    }
  }
}

/* equivalent to */
@layer base {
  html { block-size: 100%; }
}
@layer base.support {
  html body { min-block-size: 100%; }
}

/* Example nesting Scoping */
.card {
  inline-size: 40ch;
  aspect-ratio: 3/4;

  @scope (&) {
    :scope {
      border: 1px solid white;
    }
  }
}

/* equivalent to */
.card { inline-size: 40ch; aspect-ratio: 3/4; }
@scope (.card) {
  :scope { border-block-end: 1px 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;
  }
}
& 选择器在 @scope 规则中表现得像 :where(:scope)

3.4. 混合嵌套规则和声明

当一个样式规则同时包含声明以及嵌套样式规则嵌套组规则时,三者可以任意混合。出现在规则之后或其间的声明会隐式包装进嵌套声明规则,以保持相对于其他规则的顺序。

例如,在下面的代码中:
article {
  color: green;
  & { color: blue; }
  color: red;
}

/* equivalent to */
article { color: green; }
:is(article) { color: blue; }
article { color: red; }

/* NOT equivalent to */
article { color: green; }
article { color: red; }
:is(article) { color: blue; }

为了确定出现顺序嵌套样式规则嵌套组规则被视为出现在它们的父规则之后

例如:
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(除非另有定义)。

测试
嵌套选择器可以通过用父样式规则的选择器包装在:is() 选择器中来去糖。例如,
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()),如果不存在选择器列表,则为 0。

测试
例如,给出下面的样式规则:
#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()?一些非浏览器实现的类 Nesting 功能并未把它们去糖为 :is(),主要是因为它们出现在 :is() 引入之前。这些实现直接去糖,但这会导致**显著**的问题:在某些(相当常见)的情况下会意外生成**极大**的选择器,因为可能性的指数级爆炸。

.a1, .a2, .a3 {
  .b1, .b2, .b3 {
    .c1, .c2, .c3 {
      ...;
    }
  }
}

/* naively desugars to */
.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() 去糖则完全消除了这个问题,代价是让特异性稍微不那么“可用”,这被认为是一个合理的权衡。

嵌套选择器 能够匹配 无特征 元素,只要它们被父规则匹配。

虽然嵌套选择器复合选择器中的位置不会影响其行为(即 &.foo.foo& 匹配相同元素),但已有规则规定,如果出现类型选择器,它必须放在复合选择器的最前面仍然适用(即 &div 是非法的,必须写成 div&)。

测试

5. 嵌套声明规则

出于一些技术原因,能够区分出现在样式规则内容开头的属性和那些夹杂在其他规则之间的属性是很重要的。

例如,在以下两个规则中
.foo {
  color: red;
  @media (...) {...}
  background: blue;
}

我们需要对 color: redbackground: blue 稍作区别。特别是,在 CSSOM 中,color: red 作为 style 属性公开,而 background: blue 则必须出现在其 cssRules 列表中。

为实现此目的,CSS 解析会自动将这些属性包装在一个特殊的子规则中以容纳它们。然而,如果我们将它们包装在带有 & 选择器的style rule 中,会产生一些不理想的行为。

例如,在
.foo, .foo::before {
  color: red;
  & {
    background: blue;
  }
}

嵌套规则 不会background 属性应用于 .foo::before 元素,因为 & 不能表示伪元素。

同样,嵌套的非样式规则中的子声明需要以某种方式暴露为规则,因为这类规则(如@media)从未拥有 style 属性。这会遇到与上述相同的问题。

为了解决所有这些问题,我们改为将连续直接嵌套的属性序列包装在一个 嵌套声明规则 中。

除非另有说明,嵌套声明规则嵌套样式规则,并且行为与任何其他样式规则完全相同。它匹配的元素和伪元素与其父样式规则完全一致,且具有相同的特异性行为。(这 类似于 使用带有 & 选择器的样式规则,但如上所述更加强大。)

嵌套声明规则为何存在?

最初,本规范将所有样式规则中的声明组合在一起,“移动”它们到规则的前部。它还会自动将原始声明包装在 嵌套组规则 中的普通样式规则里,使用 & 选择器。

我们改用 嵌套声明规则 的两个主要原因如下。

首先,使用 & {...} 规则隐式地将声明包装在 嵌套组规则 中也会改变行为。如本注释后的示例所示,它会破坏父样式规则包含伪元素的情况,即使不是这种情况,也可能改变嵌套声明的特异性行为。改用 嵌套声明规则 可避免这些问题,使嵌套的 @media/等行为与非嵌套的 @media/等完全相同。

其次,未来 CSS 功能(尤其是“mixins”)的细节若声明交错自动移动到样式规则前部将无法正常工作。我们需要保持它们与其他规则的相对顺序,为了在 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 被隐式包装在 嵌套声明规则 中,该规则保证与其父样式规则 **完全相同** 地匹配,所以元素 **以及** 其伪元素在暗色模式页面中都会显示白色文字。

与规则交错的声明会被隐式包装在 嵌套声明规则 中,使它们成为一个单独的样式规则。例如,给定以下 CSS
.foo {
  color: black;
  @media (...) {...}
  background: silver;
}

如果检查 .foo 规则的 CSSOM 对象,其 style 属性将只包含一个声明:color: black

background: silver 声明则会出现在隐式创建的 嵌套声明子规则 中,位于 fooRule.cssRules[1].style

测试

6. CSSOM

注意: [CSSOM-1] 现在定义 CSSStyleRule 可以拥有子规则。

在序列化相对选择器嵌套样式规则时,必须将选择器绝对化,并插入隐含的嵌套选择器

例如,选择器 > .foo 将序列化为 & > .foo
测试

6.1. The CSSNestedDeclarations Interface

The CSSNestedDeclarations interface represents a 嵌套声明规则

[Exposed=Window]
interface CSSNestedDeclarations : CSSRule {
  [SameObject, PutForwards=cssText] readonly attribute CSSStyleProperties style;
};
The style attribute must return a CSSStyleProperties object for the rule, with the following properties
计算标志

未设定

只读标志

未设定

declarations

The declared declarations in the rule, in specified order.

父 CSS 规则

this

所有者节点

Null

The CSSNestedDeclarations rule serializes as if its declaration block had been serialized directly.

测试

注意: 这意味着多个相邻的 嵌套声明规则(可通过例如 insertRule)在序列化后并再次解析时会合并为单个规则。

隐私考量

本规范未报告任何新的隐私考量。

安全考量

本规范未报告任何新的安全考量。

7. 更改

2023 年 2 月 14 日工作草案 以来的重大更改

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语相结合来表达。本文档规范性部分中的关键词“MUST”(必须)、“MUST NOT”(不得)、“REQUIRED”(必需)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(推荐)、“SHOULD NOT”(不推荐)、“RECOMMENDED”(建议)、“MAY”(可以)和“OPTIONAL”(可选)应按照 RFC 2119 中的描述进行解释。然而,为了可读性,这些词在本文档中不以全大写形式出现。

本规范的所有文本均为规范性文本,明确标记为非规范性的部分、示例和注释除外。 [RFC2119]

本规范中的示例均以“例如”开头,或使用 class="example" 与规范性文本隔开,如下所示

这是一个说明性示例。

提示性说明以“Note”开头,并使用 class="note" 与规范性文本隔开,如下所示

注意,这是一个说明性注释。

建议(Advisements)是旨在引起特别注意的规范性部分,并使用 <strong class="advisement"> 与其他规范性文本隔开,如下所示: UA 必须提供可访问的替代方案。

测试

与本规范内容相关的测试可记录在“Tests”块中,就像这一个一样。任何此类块都是非规范性的。


一致性类别

本规范为三类一致性定义了一致性要求。

样式表
一份 CSS 样式表
渲染器
一种 用户代理 (UA),它解释样式表的语义并渲染使用它们的文档。
创作工具
一种 用户代理 (UA),用于编写样式表。

如果样式表包含的所有使用本模块定义语法的语句,根据通用 CSS 语法及本模块定义的各功能语法均有效,则该样式表符合本规范。

如果渲染器除了按相应规范解释样式表外,还通过正确解析本规范定义的所有功能并相应地渲染文档来支持这些功能,则该渲染器符合本规范。然而,由于设备限制导致 UA 无法正确渲染文档,并不意味着该 UA 不符合规范。(例如,UA 无需在单色显示器上渲染颜色。)

如果创作工具编写的样式表根据通用 CSS 语法及本模块中各功能的语法是句法正确的,并符合本模块中描述的所有其他样式表一致性要求,则该创作工具符合本规范。

部分实现

为了使作者能够利用前向兼容的解析规则来指定后备值,CSS 渲染器 **必须** 将其无法使用支持级别的任何 @规则、属性、属性值、关键字和其他语法结构视为无效(并 适当忽略)。特别地,用户代理 **不得** 在单一多值属性声明中选择性地忽略不支持的组件值而保留支持的值:如果任何值被视为无效(因为不支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有特性的实现

为了避免与未来稳定的 CSS 功能发生冲突,CSS 工作组建议在实施不稳定功能和私有扩展遵循最佳实践

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现即可成为可能,实现者应发布他们能够证明根据规范正确实现的任何 CR 级别特性的无前缀实现。

为建立并保持 CSS 在不同实现间的互操作性,CSS 工作组请求非实验性的 CSS 渲染器在发布任何 CSS 功能的无前缀实现之前,向 W3C 提交一份实现报告(并在必要时提交用于该实现报告的测试用例)。提交给 W3C 的测试用例需经 CSS 工作组审阅和修正。

有关提交测试用例和实现报告的详细信息,请访问 CSS 工作组网站 https://w3org.cn/Style/CSS/Test/。问题可发送至 public-css-testsuite@w3.org 邮件列表。

索引

本规范定义的术语

通过引用定义的术语

引用

规范性引用

[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS 层叠与继承第 4 级. 2022年1月13日. CR. URL: https://w3org.cn/TR/css-cascade-4/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 级联与继承 Level 6. 2024 年 9 月 6 日. 工作草案 (WD). URL: https://w3org.cn/TR/css-cascade-6/
[CSS-COLOR-4]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS 颜色模块 Level 4. 2025 年 4 月 24 日. CRD. URL: https://w3org.cn/TR/css-color-4/
[CSS-CONDITIONAL-3]
Chris Lilley; David Baron; Elika Etemad. CSS 条件规则模块 3 级 (CSS Conditional Rules Module Level 3). 2024年8月15日. CRD. URL: https://w3org.cn/TR/css-conditional-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS 语法模块 3 级 (CSS Syntax Module Level 3). 2021年12月24日. CRD. URL: https://w3org.cn/TR/css-syntax-3/
[CSS21]
Bert Bos; et al. 层叠样式表 2 级修订版 1 (CSS 2.1) 规范 (Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification). 2011年6月7日. REC. URL: https://w3org.cn/TR/CSS2/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021年8月26日. WD. URL: https://w3org.cn/TR/cssom-1/
[RFC2119]
S. Bradner. RFC 中用于指示要求级别的关键词. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器第 4 级. 2022 年 11 月 11 日. WD. URL: https://w3org.cn/TR/selectors-4/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/

参考资料

[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS 背景与边框模块 3 级 (CSS Backgrounds and Borders Module Level 3). 2024年3月11日. CRD. URL: https://w3org.cn/TR/css-backgrounds-3/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 2022年1月13日. CR. URL: https://w3org.cn/TR/css-cascade-5/
[CSS-CONDITIONAL-5]
Chris Lilley; et al. CSS 条件规则模块 5 级 (CSS Conditional Rules Module Level 5). 2025年10月30日. WD. URL: https://w3org.cn/TR/css-conditional-5/
[CSS-PSEUDO-4]
Elika Etemad; Alan Stearns. CSS 伪元素模块 Level 4. 2025 年 6 月 27 日. WD. URL: https://w3org.cn/TR/css-pseudo-4/
[CSS-UI-4]
Tab Atkins Jr.; Florian Rivoal. CSS 基本用户界面模块 4 级 (CSS Basic User Interface Module Level 4). 2026年1月20日. WD. URL: https://w3org.cn/TR/css-ui-4/

IDL 索引

[Exposed=Window]
interface CSSNestedDeclarations : CSSRule {
  [SameObject, PutForwards=cssText] readonly attribute CSSStyleProperties style;
};

问题索引

上一段在我们将 & 本身移至 Selectors 时需要移动到 Selectors;这里为了方便我做了临时修改。
我们希望放宽此限制,但必须同时对 :is() 和 & 进行,因为它们有意基于相同的底层机制构建。(Issue 7433