1. 引言与缺失部分
这是一个关于 CSS 级联与继承 第5级 的差异规范。 它目前是探索性工作草案: 如果你正在实现任何内容,请参考第5级。 一旦本草案达到 CR,我们将合并第5级的文本。
2. 级联
级联 处理给定元素上某属性的一组无序 声明值, 按照下述方式根据 声明 的优先级进行排序, 并输出一个单一的 级联值。
2.1. 层叠排序顺序
层叠会根据以下标准对声明进行排序,按优先级递减:
- 来源和重要性
-
声明的来源取决于其出处,
以及其重要性,即是否使用了!important(见下文)。
各种来源的优先级从高到低为:
- 过渡声明 [css-transitions-1]
- 重要的 用户代理声明
- 重要的 用户声明
- 重要的 作者声明
- 动画声明 [css-animations-1]
- 普通的 作者声明
- 普通的 用户声明
- 普通的 用户代理声明
列表中靠前的来源声明优先于后面的来源声明。
- 上下文
-
文档语言可以提供来自不同封装上下文的声明的混合,例如在树上下文中嵌套的影子树。
当比较来自不同封装上下文的两个声明时, 对于普通的规则, 外部上下文的声明优先, 对于重要的规则, 内部上下文的声明优先。 为此,[DOM]中 的 树上下文被认为是嵌套在 包含阴影的树顺序中。
注意:这实际上意味着属于某个 封装上下文的普通声明可以设置默认值, 这些默认值容易被外部上下文覆盖, 而属于某个封装上下文的重要声明 可以强制要求这些声明不能被外部上下文覆盖。
- 样式属性
- 分别对于普通和重要的声明, 直接附加到元素上的声明 (例如样式属性的内容) 优先于通过样式规则选择器间接映射的声明。
- 层
-
每个声明可以被显式分配到
来源和上下文中的
层叠层。
在本步骤中,
没有分配到显式层的声明会被加入到一个隐式的最终层。
层叠层(与声明一样)按出现顺序进行排序, 见 § 2.4.1 层顺序。 当比较属于不同层的声明时, 对于普通规则, 在层顺序中最新的层叠层中的声明获胜, 而对于重要规则, 在层顺序中最早的层叠层中的声明获胜。
- 特异性
- 选择器模块 [SELECT]描述了如何计算选择器的特异性。 每个声明的特异性与它所出现的样式规则的特异性相同。 具有最高特异性的声明获胜。
- 范围接近性
- 当比较在样式规则中出现的声明时, 这些规则具有不同的作用范围根, 则声明的作用范围根与 范围样式规则的 主题之间的代际或兄弟元素跳跃次数越少,声明越优先。 对于没有作用范围根的样式规则,视为具有无限接近跳跃次数。
- 出现顺序
-
文档顺序中最后的声明获胜。
为此:
- 样式表的顺序如 最终 CSS 样式表中所示。
- 来自导入样式表的声明按其样式表替换 @import规则的位置顺序。
- 由源文档独立链接的样式表中的声明被视为按链接顺序串联起来, 链接顺序由主机文档语言决定。
- 来自样式属性的声明按其所在元素的文档顺序进行排序, 且都排在任何样式表之后。[CSSSTYLEATTR]
层叠的输出 是每个元素上每个属性的(可能为空的)排序列表 已声明值。
2.2. 层叠来源
层叠来源
2.3. 重要声明:!important 注释
CSS 层叠 5 § 6.3 重要声明: !important 注释
重要 普通
2.4. 层叠层
2.4.1. 层顺序
2.5. 作用域样式:@scope 规则
作用域是文档的一个子树或片段, 可以被选择器用于更有针对性的匹配。 作用域通过以下方式确定:
如果一个元素满足以下条件,则该元素为在作用域内:
注意:与阴影封装不同, 阴影封装在 DOM 中描述了一个持续的一对一关系, 关系发生在阴影宿主与其嵌套的阴影树之间, 而多个重叠的作用域可以与相同的元素建立关系。
作用域样式在 CSS 中使用@scope 块 at 规则描述, 该规则声明了一个作用域根和一组关联的可选作用域限制以及一组样式规则。
@scope ( .light-scheme) { /* 仅匹配 light-scheme 内的链接 */ a{ color : darkmagenta; } } @scope ( .dark-scheme) { /* 仅匹配 dark-scheme 内的链接 */ a{ color : plum; } } @scope ( .media-object) { /* 仅匹配 media-object 内的作者图片 */ .author-image{ border-radius : 50 % ; } }
@scope ( .media-object) to( .content > *) { img{ border-radius : 50 % ; } .content{ padding : 1 em ; } }
img选择器将仅匹配 DOM 片段中起始于任何 .media-object并包括其到 .content类的任何子节点的图像标签。
是否应在 作用域选择器的定义中添加作用域限制?
2.5.1. @scope 的影响
@scope at 规则对其包含的 样式规则有三个主要影响:
-
:scope 选择器被定义为匹配 @scope 规则的作用域根, 包括当该宿主为作用域根时的无特征阴影宿主。 & 选择器被定义为表示 代表 作用域根 的选择器(<scope-start> 选择器), 或者如果未指定选择器则表示 :scope。
-
层叠优先考虑具有 更接近的 作用域根的声明, 不考虑特异性或出现顺序, 通过在作用域根和每个 选择器对象之间应用 作用域接近性,以优先考虑 作用域样式规则。
注意:与嵌套不同, @scope 规则中的选择器 不会继承 @scope 前言中的父选择器的特异性。
@scope ( #hero) { img{ border-radius : 50 % ; } } :where ( #hero) img{ border-radius : 50 % ; }
额外的 #hero 选择器特异性
不适用于作用域选择器的特异性。
然而,由于其中一个
img
选择器具有作用域,
因此该选择器在层叠中被赋予更高的权重,
通过应用作用域接近性。
main-component
和 sub-component
)
并且每个元素都通过使用 data-scope
属性标记为一个或两个作用域的一部分:
< section data-scope = "main-component" > < p data-scope = "main-component" > ...< p > <!-- sub-component root is in both scopes --> < section data-scope = "main-component sub-component" > <!-- children are only in the inner scope --> < p data-scope = "sub-component" > ...< p > </ section > </ section >
然后这些自定义作用域属性会附加到 CSS 中的每个选择器上:
p[ data-scope~='main-component' ] { color : red; } p[ data-scope~='sub-component' ] { color : blue; } /* 两个部分都是外层作用域的一部分 */ section[ data-scope~='main-component' ] { background : snow; } /* 内部部分也是内部作用域的一部分 */ section[ data-scope~='sub-component' ] { color : ghostwhite; }
使用 @scope 规则, 作者和工具可以仅通过将唯一的属性或类应用于 作用域根来复制类似的行为:
< section data-scope = "main-component" > < p > ...< p > < section data-scope = "sub-component" > < p > ...< p > </ section > </ section >
然后类或属性可以用于同时建立上限和下限。 由下限选择器匹配的元素将被排除在结果作用域之外, 这样作者可以默认创建不重叠的作用域:
@scope ([ data-scope='main-component' ]) to([ data-scope]) { p{ color : red; } /* 仅外层部分是外层作用域的一部分 */ section{ background : snow; } } @scope ([ data-scope='sub-component' ]) to([ data-scope]) { p{ color : blue; } /* 内层部分仅是内部作用域的一部分 */ section{ color : ghostwhite; } }
然而,作者可以使用子代组合器和通用选择器创建重叠的作用域边界, 使得内部作用域根成为两个作用域的一部分:
@scope ([ data-scope='main-component' ]) to([ data-scope] > *) { p{ color : red; } /* 两个部分都是外层作用域的一部分 */ section{ background : snow; } }
2.5.2. @scope 的语法
@scope 规则的语法为:
@scope [(<scope-start>)]? [to (<scope-end>)]? { <rule-list> }
其中:
-
<scope-start> 是用于识别 <选择器列表> 选择器 用于标识作用域根。
-
<scope-end> 是用于识别任何 <选择器列表> 选择器 用于标识任何作用域限制。
-
<rule-list> 表示 作用域样式规则。
伪元素不能作为作用域根或 作用域限制; 它们在 <scope-start> 和 <scope-end> 中都是无效的。
2.5.3. 作用域样式规则
作用域样式规则 与非作用域规则在以下方面有所不同:
@scope ( #my-component) { p{ color : green; } :scope p{ color : green; } }
作者可以通过添加显式的组合器来调整隐含的关系:
@scope ( #my-component) { > p{ color : green; } :scope > p{ color : green; } }
作者还可以在选择器中通过包含 作用域根 来定位或显式地对其进行定位, 使用 :scope 或 &:
@scope ( #my-component) { :scope{ border : thin solid; } &{ border : thin solid; } main :scope p{ color : green; } main & p{ color : green; } }
虽然:scope 或 & 选择器 都可以引用作用域根, 但在此上下文中它们有不同的含义:
- 选择器匹配的差异
-
:scope 选择器将仅匹配 作用域根本身, 而& 选择器能够匹配任何由 <scope-start> 选择器列表 匹配的元素。
- 选择器特异性的差异
-
:scope 选择器的特异性 等同于其他伪类, 而& 选择器的特异性等于 <scope-start> 中 最特定的选择器。
2.5.4. 识别作用域根和限制
- 找到 作用域根
-
对于由 <scope-start> 匹配的每个元素, 使用该元素创建一个作用域作为 作用域根。 如果未指定 <scope-start>, 则 作用域根为定义 @scope 规则的样式表的 父元素。 (如果不存在这样的元素,并且包含的节点树是一个 影子树, 则 作用域根为 影子宿主。 否则, 作用域根为包含的 节点树的根节点。) <scope-start> 中的任何 :scope 或 & 选择器在其外部上下文中定义。
- 找到任何 作用域限制
-
对于由 作用域根创建的每个 作用域, 其作用域限制设置为 匹配 <scope-end> 且 在作用域内的所有元素, 解释 :scope 和 & 与 作用域样式规则 中完全相同。
style
元素建立局部作用域。
例如:
< div > < style > @ scope { p { color : red ; } } </ style > < p > this is red</ p > </ div > < p > not red</ p >
这相当于:
< div id = "foo" > < style > @ scope ( # foo ) { p { color : red ; } } </ style > < p > this is red</ p > </ div > < p > not red</ p >
/* .content 仅当它是 :scope 的直接子元素时才是限制 */ @scope ( .media-object) to( :scope > .content) { ...}
作用域限制还可以通过使用 :scope 引用其作用域根外部的元素。 例如:
/* .content 仅当 :scope 位于 .sidebar 内时才是限制 */ @scope ( .media-object) to( .sidebar :scope .content) { ...}
2.5.5. 作用域嵌套
@scope 规则可以嵌套。 在这种情况下,就像嵌套样式规则一样, 内部 @scope 的前导选择器(那些定义其 作用域) 由外部选择器限定。
注意:对于进一步嵌套的 作用域样式规则,结果作用域实际上受到外部和内部 @scope 规则的约束, 但作用域根由最内部的 @scope 定义。 由于作用域接近度是测量 作用域样式规则的 对象与作用域根之间的距离, 所以对于嵌套的 @scope 规则,只有最内部的 @scope 才重要。
作用域接近度计算是否应受嵌套作用域的影响? [Issue #10795]
@scope ( .parent-scope) { @scope ( :scope > .child-scope) to( :scope .limit) { :scope .content{ color : red; } } }
相当于:
@scope ( .parent-scope > .child-scope) to( .parent-scope > .child-scope .limit) { .parent-scope > .child-scope .content{ color : red; } }
全局名称定义的at 规则, 例如 @keyframes、@font-face 或 @layer,如果定义在 @scope 内是有效的, 但它们不会被封闭的 @scope 规则所作用或影响。 但是,由这些规则包含的任何 样式规则(例如在 @layer 中) 都是作用域样式规则。
2.6. 非CSS呈现提示的优先级
3. CSSOM
3.1.
CSSScopeRule
接口
CSSScopeRule
接口表示 @scope 规则:
[Exposed =Window ]interface :
CSSScopeRule CSSGroupingRule {readonly attribute CSSOMString ?;
start readonly attribute CSSOMString ?; };
end
start
类型为CSSOMString
start
属性返回序列化规则的 <scope-start> 的结果 (不包括外围括号), 如果没有 <scope-start>,则为 null。end
类型为CSSOMString
end
属性返回序列化规则的 <scope-end> 的结果 (不包括外围括号), 如果没有 <scope-end>,则为 null。
4. 更改
本附录是信息性的。
4.1. 自 2023 年 3 月 21 日工作草案以来的更改
自2023 年 3 月 21 日工作草案以来的重大更改包括:
-
:scope 选择器可以匹配 无特征的 shadow host,当该 host 是 作用域根 元素时。 (Issue 9025)
-
<scope-start> 和 <scope-end> 选择器是不宽容的。 (Issue 10042)
-
没有 <scope-start> 的 @scope 规则作用于 shadow host,而不是 shadow root。 (Issue 9178)
-
澄清了作用域接近度是单一的测量步骤, 用于测量一个 作用域根和作用域样式规则的 对象之间的步骤。 (Issue 10795 已经打开以进一步讨论此问题)。
-
移除了强作用域接近度。 (Issue 6790)
-
移除了作用域后代组合符(延后处理)。 (Issue 8628)
-
新增了
CSSScopeRule
接口。 (Issue 8626)
4.2. 自 2021 年 12 月 21 日首次公开工作草案以来的更改
自2021 年 12 月 21 日首次公开工作草案以来的重大更改包括:
-
澄清了 @scope 对嵌套的 :scope 和 & 选择器的影响。 (Issue 8377)
-
从特异性计算中移除了 @scope 前导符。 (Issue 8500)
-
指定了名称定义的 at 规则 在 @scope 中的行为。 (Issue 6895)
-
通过使 <scope-start> 可选来添加隐式作用域。 (Issue 6606)
-
在 @scope 前导符中禁止使用 伪元素。 (Issue 7382)
-
移除了选择器作用域符号。 (Issue 7709)
-
作用域限制元素被排除在 结果 作用域之外。 (Issue 6577)
4.3. 自第 5 级以来的新增内容
自第 5 级以来,添加了以下功能:
-
定义了作用域,由 <scope-start> 和 <scope-end> 选择器组合描述。
-
用于选择具有下限的 :in() 伪类。
-
用于创建作用域样式表的 @scope 规则。
-
在层叠中定义了作用域接近度。
4.4. 自第 4 级以来的新增内容
自第 4 级以来,添加了以下功能:
-
引入了用于定义层叠层的 @layer 规则。
-
向 @import 定义中添加了 layer/layer() 选项。
-
引入了用于将值回滚到以前层的 revert-layer 关键字。
4.5. 自第 3 级以来的新增内容
自第 3 级以来,添加了以下功能:
-
引入了用于回滚层叠的 revert 关键字。
-
引入了用于支持条件 supports() 语法的 @import 规则。
-
定义了 CSS 用于支持旧版语法的两种属性别名机制。参见CSS 层叠 4 § 3.1 属性别名。
4.6. 自第 2 级以来的新增内容
自第 2 级以来,添加了以下功能:
致谢
David Baron, Tantek Çelik, Keith Grant, Giuseppe Gurgone, Theresa O’Connor, Florian Rivoal, Noam Rosenthal, Simon Sapin, Jen Simmons, Nicole Sullivan, Lea Verou, 和 Boris Zbarsky 对本规范作出了贡献。
5. 隐私注意事项
-
通过应用样式规则表达的用户偏好和用户代理默认值 会在层叠过程中暴露, 并且可以通过它们应用于文档的计算样式推断出。
6. 安全注意事项
-
层叠过程不区分同源和跨源样式表, 这使得可以从它们应用于文档的计算样式推断出跨源样式表的内容。
-
@import 规则假定没有
Content-Type
元数据 的资源(或在主文档处于怪癖模式下的任何同源文件) 是text/css
, 这可能导致任意文件被导入到页面并被解释为 CSS, 从而可能通过它们应用于文档的计算样式推断出敏感数据。