CSS 属性和值 API 第 1 级

W3C 工作草案,

关于此文档的更多详细信息
此版本:
https://www.w3.org/TR/2024/WD-css-properties-values-api-1-20240326/
最新发布版本:
https://www.w3.org/TR/css-properties-values-api-1/
编辑草案:
https://drafts.css-houdini.org/css-properties-values-api-1/
以前版本:
历史:
https://www.w3.org/standards/history/css-properties-values-api-1/
反馈:
public-houdini@w3.org 主题行中注明“[css-properties-values-api] … 消息主题 …” (归档)
GitHub
编辑:
Tab Atkins-Bittner (谷歌)
前编辑:
规则适用。


摘要

此 CSS 模块定义了一个 API,用于注册新的 CSS 属性。使用此 API 注册的属性将提供解析语法,以定义类型、继承行为和初始值。

此文档的状态

本节描述此文档在发布时的状态。 当前 W3C 发布列表 和此技术报告的最新修订 可以在 W3C 技术报告索引中找到 https://www.w3.org/TR/.

此文档由 CSS 工作组 发布为 工作草案 使用 推荐 路线。 作为工作草案发布 并不意味着 W3C 及其成员的认可。

这是一个草案文档 可能会被其他文档更新、替换 或在任何时间废止。 不适合将此文档引用为工作进展之外的内容。

请通过 在 GitHub 上提交问题(首选), 在标题中包含规范代码“css-properties-values-api”,例如: “[css-properties-values-api] …评论摘要…”。 所有问题和评论都会被 存档。 或者,反馈可以发送至(存档)公共邮件列表 www-style@w3.org

此文档受 2023年11月3日 W3C 过程文档 的管辖。

此文档由一组根据 W3C 会员W3C 专利政策 提供的贡献者撰写。

1. 介绍

CSS 定义了一套全面的属性,可以通过操作这些属性来修改网页文档的布局、绘制或行为。然而,网页作者常常希望通过额外的属性来扩展这套属性。

[css-variables] 提供了定义用户控制属性的基本方法, 但这些属性总是以令牌列表作为值,必须始终继承,并且只能通过 var() 引用重新并入其他属性的值中,来影响文档的布局或绘制。

本规范扩展了[css-variables],允许注册具有值类型、初始值和定义的继承行为的属性, 通过两种方法:

本规范是[css-paint-api-1][css-layout-api-1]的补充, 允许自定义属性直接影响绘制和布局行为。

2. 注册的自定义属性

自定义属性可以成为一个注册的自定义属性, 使其更像用户代理定义的属性: 赋予它一个由用户代理检查的语法, 一个初始值, 和特定的继承行为。 这可以通过@property 规则, 或registerProperty() JS 函数来实现。

自定义属性文档中被视为注册, 如果其名称在文档的样式表中有一个有效的@property 规则定义, 或其名称在文档的[[registeredPropertySet]] 槽中包含 (即,registerProperty() 被调用来注册它)。

注册的自定义属性 的行为类似于未注册的 自定义属性, 只是如下面定义的那样。

2.1. 确定注册

一个注册的自定义属性具有一个自定义属性注册, 包含处理它如真实属性所需的所有数据。 它是一个结构 ,由以下内容组成:

如果文档[[registeredPropertySet]]包含一个记录,其自定义属性的名称, 注册即该记录。

否则, 如果文档的 活动样式表包含至少一个有效的@property 规则 表示与自定义属性的名称的注册, 文档顺序中的最后一个注册即为该注册。

否则没有注册, 并且自定义属性不是一个注册的自定义属性

2.2. 解析时行为

注册的自定义属性的解析方式与未注册的自定义属性完全相同; 几乎允许任何内容。 属性的注册语法在解析时被检查。

注意:然而, 语法在计算值时被检查, 在通过var()进行替换之前。 参见§ 2.4 计算值时的行为

为什么不对自定义属性进行语法检查?

在解析页面的 CSS 时, 用户代理通常会进行多项优化 以帮助提高速度和内存使用。

其中一个优化 是仅存储实际会产生影响的属性; 它们会丢弃无效的属性, 如果在单个声明块中多次写入同一属性, 除最后一个有效的属性外,所有其他属性都会被丢弃。 (这是 CSS 的错误恢复 和向前兼容行为的重要部分。)

如果属性的语法在页面的生命周期内从未变化,这种方法是有效的。 但是,如果自定义属性已注册, 它可以更改其语法, 以便之前无效的属性 突然变为有效。

处理这一点的唯一方法是要么存储每个声明, 即使那些最初无效的声明 (增加页面的内存成本), 要么使用新的语法规则重新解析整个页面的 CSS (增加注册自定义属性的处理成本)。 这两者都不是非常理想的选择。

此外, 用户代理定义的属性的语法由用户查看页面时的用户代理版本决定; 这超出了页面作者的控制范围, 这就是 CSS 的错误恢复行为的整个原因 和针对不同支持级别编写多个声明的实践。 而自定义属性的语法由页面作者控制, 根据他们在页面中包含的样式表或脚本; 没有不可预测性需要管理。 丢弃违反语法的自定义属性 因此只会对页面作者来说是一种便利, 而不是像用户代理定义的属性那样的必要性。

2.3. 指定值-时间行为

就像未注册的自定义属性一样, 所有注册自定义属性,无论注册语法如何, 都接受CSS宽关键字, 例如继承还原。 其行为在CSS 级联 4 § 7.3 明确默认值中定义。

2.4. 计算值-时间行为

计算值注册自定义属性由其注册的语法决定。

如果注册的语法是通用语法定义, 则计算值与未注册的自定义属性相同 (要么是替换变量后的指定值,要么是保证无效值)。

否则,尝试解析该属性的值 根据其注册语法。 如果失败, 声明在计算值时间无效,而计算值将相应确定。 如果成功, 计算值依赖于语法的具体情况:

对于"<length>""<length-percentage>""<angle>""<time>""<resolution>""<integer>""<number>"、 和"<percentage>"值:

对于"<color>"值, 通过解析颜色值来计算值, 根据CSS 颜色 4 §  14. 解析<color>值

对于"<custom-ident>"、标识符或"*"值, 计算值如指定。

对于"<url>"值, 计算值为以下之一:

URL 行为示例
因为 URL 解析相对于其所在样式表的基本 URL, 我们可以 得到多个相对 URL,这些 URL 解析相对于不同的基本 URL,即使 它们出现在同一个属性中。

例如,假设--url-foo--url-bar是具有<url>语法的注册 自定义属性,并且我们有一个样式表在/style/foo/foo.css

div {
  --url-foo: url("foo.png");
}

还有另一个样式表在/style/bar/bar.css

div {
  --url-bar: url("bar.png");
}

最后,一个文档在/index.html:

<link href="/style/foo/foo.css" rel="stylesheet" type="text/css">
<link href="/style/bar/bar.css" rel="stylesheet" type="text/css">
<div style="background-image: var(--url-foo), var(---url-bar);">
</div>

在这里,var(--url-foo) 引用会生成一个解析为/style/foo的URL,而var(--url-bar) 引用会生成一个解析为/style/bar的URL。

另一方面,如果--url-foo--url-bar都是注册的,它们将把它们的字面值(相对URL)替换到/index.html样式表中,然后将这些URL解析为/index.html

对于"<image>"值,计算值是计算的<image>

对于"<transform-function>""<transform-list>"值,计算值按规定生成,但所有长度会解析为其计算值。

对于带有乘数的值,计算值是基本类型的计算值列表。

对于用| 组合符指定的语法,计算值由匹配该值的第一条子句的计算值规则应用给出。

2.5. 动画行为

注意: 根据[css3-animations][css3-transitions]的定义,可以指定引用自定义属性的动画和过渡。

当通过动画和过渡引用时,自定义属性值会插值 按计算值,根据解析的类型。

注意: 这意味着值的列表,如<color>+<color>#,会插值为简单列表,逐个匹配每个组件索引,如果组件数量不匹配则会失败。

作为上述规则的例外,解析为<transform-list><transform-function><transform-function>+的值则按transform属性插值。

注意: 如果出于某种原因,自定义属性定义为<transform-function>#,则首先会插值为简单列表,然后每个列表项将插值为transform值。

注意: 注册(或更改注册)自定义属性可以改变其计算值,这可以开始或中断CSS过渡。

2.6. 条件规则

§ 2.2 解析时行为中所述,无论是未注册的还是注册的 自定义属性在解析时都接受(几乎)所有可能的值。注册的 自定义属性仅在计算值时应用其语法。

因此,所有自定义属性,无论是注册还是未注册,都将在@supports规则中测试为“true”,只要不违反自定义属性的(非常宽松的)通用语法。

例如,即使自定义属性以syntax: "<color>";注册,像@supports (--foo: 1em) {...}这样的规则仍会评估为true并应用这些样式,因为该声明确实成功解析为有效的属性。

2.7. 通过 var() 的替换

与未注册的自定义属性一样, 注册的自定义属性的值可以使用 var() 函数替换为另一个值。 然而,注册的自定义属性作为其 计算值 进行替换,而不是用于生成该值的原始标记序列。

任何引用注册自定义属性的 var() 函数 必须被替换为 等效标记序列, 它等于通过 序列化 计算值生成的标记序列, 并 标记化 结果字符串。

假设 --x 是以 <length> 语法注册的, 并且 '--y' 是一个未注册的自定义属性。
div {
  font-size: 10px;
  --x: 8em;
  --y: var(--x);
}

因为 --x 的计算值(序列化时) 是 "80px",所以 --y 的计算值是 一个 <dimension-token>,其值为 "80" 和单位 "px"。

2.7.1. var() 引用中的后备值

使用 var() 函数引用注册自定义属性 时 可以提供后备值。然而,后备值必须与被引用的自定义属性的 语法定义 匹配,否则声明在 计算值时间无效

注意: 无论后备值是否被使用,这都适用。

2.7.2. 通过相对单位的依赖循环

注册自定义属性 遵循与未注册的 自定义属性 相同的依赖循环解析规则, 并附加以下约束:

对于任何具有 <length><length-percentage> 语法组件的注册自定义属性:

例如,给定以下注册:
CSS.registerProperty({
  name: "--my-font-size",
  syntax: "<length>",
  initialValue: "0px",
  inherits: false
});

以下代码将产生一个依赖循环:

div {
  --my-font-size: 10em;
  font-size: var(--my-font-size);
}

font-size 的行为将表现得好像指定了 unset 值。

2.8. 影子 DOM

与 CSS 中的许多概念不同 (参见 CSS Scoping 1 § 3.5 名称定义构造和继承), 属性注册 不是 作用于树范围。 所有注册, 无论它们出现在最外层文档中 还是在影子树中, 都在一个全球注册图中交互, 适用于 文档

为什么注册不能作用于范围?

对于属性注册作用于范围的情况是明确的—​使用影子 DOM 的组件 并注册一些自定义属性 可能并不打算让外部页面 查看该注册, 因为外部页面甚至不知道该组件正在使用该属性。

然而,也有不作用于注册范围的理由—​自定义属性用于将数据 导入 组件, 外部页面能够设置这些自定义属性 并让注册进行语法检查是很有用的; 同样,属性的初始值等概念 只有在属性注册全局存在时才有意义, 因此它适用于文档根部的属性。

但以上只是意味着注册范围 可能是应当可控的东西, 而不是强制全局。

注册必须是全局的原因 是因为元素可以同时存在于多个树范围中, 各个树范围的样式 会交错并共同级联。 这适用于 宿主元素, 它生活在外部树中 但可以通过 :host 选择器从影子树中进行样式化, 同样,影子 DOM 内的元素 也可以通过外部树中的 ::part() 伪元素进行目标选择。

如果注册可以作用于树范围, 而一个单一属性在内外两处注册, 那么不清楚应该应用哪个注册 来解析值。 即使我们追踪值来自哪个树 (这是我们对其他树作用值所做的) 并应用相应的注册, 也不清楚这是否会产生合理的结果—​影子 DOM 可能期望某个属性有 特定的值空间, 并且在接收到完全不同的值时会感到惊讶, 因为外部树赢得了级联 并应用了它自己的注册。

当自定义属性作为使用影子 DOM 的组件的公共 API 的一部分暴露时, 这种全局注册行为会按预期工作。 如果外部页面使用同名的自定义属性 进行不同目的, 那已经是需要解决的冲突, 而注册行为并没有使情况变得更糟。

然而,如果自定义属性旨在用于组件的私有内部使用, 建议给该属性 取一个可能唯一的名称, 以最小化与其他上下文发生冲突的可能性。 这可以通过包含项目名称 或一些简短的随机字符串 来实现。

3. @property 规则

@property 规则在样式表中直接表示 自定义属性注册 而无需运行任何 JS。 有效的 @property 规则会导致一个 注册的自定义属性, 就好像 registerProperty() 被调用并使用了等效的参数。

@property 的语法是:

@property <custom-property-name> {
  <declaration-list>
}

有效的 @property 规则表示一个 自定义属性注册, 其属性名称为规则前导中的 <custom-property-name> 的序列化。

@property 规则需要 语法继承 描述符; 如果缺少任一项, 整个规则都是无效的,必须被忽略。 初始值 描述符只有在语法为 通用语法定义 时是可选的, 否则该描述符是必需的; 如果缺失,整个规则无效,必须被忽略。

未知的描述符是无效的并被忽略, 但不会使 @property 规则无效。

注意:§ 2.1 确定注册 中规定, 如果为同一个 <custom-property-name> 定义多个有效的 @property 规则, 则样式表中最后一个的“胜出”。 来自 CSS.registerProperty() 的自定义属性注册优先于同一个 <custom-property-name> 的任何 @property 规则。

3.1. 语法描述符

名称: 语法
适用于: @property
值: <string>
初始: 不适用 (见正文)

指定由 自定义属性注册 表示的 @property 规则的语法, 控制属性值在 计算值 时的解析。

语法 描述符是 @property 规则有效的必需项; 如果缺失,@property 规则无效。

如果提供的字符串不是有效的 语法字符串 (如果在调用 消费语法定义 时返回失败), 则该描述符无效,必须被忽略。

3.2. inherits 描述符

名称: inherits
适用于: @property
值: true | false
初始: n/a(见正文)

指定由 自定义属性注册 代表的 @property 规则的继承标志,控制属性是否默认继承。

inherits 描述符对于 @property 规则是必需的; 如果缺失,则 @property 规则无效。

3.3. initial-value 描述符

名称: initial-value
适用于: @property
值: <declaration-value>?
初始: 保证无效值(但见正文)

指定由 自定义属性注册 代表的 @property 规则的初始值,控制属性的 初始值

如果 syntax 描述符的值为 通用语法定义, 则 initial-value 描述符是可选的。 如果省略,属性的 初始值保证无效值

否则, 如果 syntax 描述符的值不是 通用语法定义, 则必须满足以下条件,以使 @property 规则有效:

如果不满足上述条件,则 @property 规则无效。

4. 在 JS 中注册自定义属性

要通过 JS 注册自定义属性, CSS 对象扩展了一个 registerProperty() 方法:

dictionary PropertyDefinition {
  required DOMString name;
           DOMString syntax       = "*";
  required boolean   inherits;
           DOMString initialValue;
};

partial namespace CSS {
  undefined registerProperty(PropertyDefinition definition);
};

Additional, the Document object gains a new [[registeredPropertySet]] private slot, which is a set of records that describe registered custom properties.

4.1. registerProperty() 函数

registerProperty(PropertyDefinition definition) 方法 根据 definition 中提供的配置选项注册自定义属性。 当调用时, 它执行 注册自定义属性 算法, 将 definition 参数中的选项作为相同名称的参数传递。

注册一个 自定义属性,其中 name 为字符串, 可选的 syntax 为字符串,inherits 为布尔值, initialValue 为字符串, 执行以下步骤:
  1. property set当前全局对象的 关联的 Document[[registeredPropertySet]] 槽的值。

  2. 如果 name 不是 自定义属性名称字符串抛出 SyntaxError 并退出此算法。

    如果 property set 已包含 name 作为其属性名称的条目 (按代码点比较), 抛出 InvalidModificationError 并退出此算法。

  3. 尝试从 syntax消费一个语法定义。 如果返回失败, 抛出 SyntaxError。 否则,让 syntax definition 为返回的 语法定义

  4. 如果 syntax definition通用 语法定义, 且 initialValue 不存在, 让 parsed initial value 为空。 这必须与自定义属性的“默认”初始值相同, 如 [css-variables] 中定义。 跳到算法的下一步。

    否则, 如果 syntax definition通用 语法定义解析 initialValue<declaration-value>。 如果失败, 抛出 SyntaxError 并退出此算法。 否则, 让 parsed initial value 为解析结果。 跳到算法的下一步。

    否则,如果 initialValue 不存在, 抛出 SyntaxError 并退出此算法。

    否则, 解析 initialValue 根据 syntax definition。 如果失败, 抛出 SyntaxError 并退出此算法。

    否则,让 parsed initial value 为解析结果。 如果 parsed initial value 不是 计算独立的抛出 SyntaxError 并退出此算法。

  5. inherit flag 设置为 inherits 的值。

  6. registered property 为一个 结构体,其属性 名称为 name, 语法为 syntax definition, 初始值为 parsed initial value, 以及继承标志为 inherit flag附加 registered propertyproperty set

属性值是 计算独立的,如果它可以仅使用元素上属性的值和不能被 CSS 改变的“全局”信息转换为计算值。

例如, 5px计算独立的, 因为将其转换为计算值并不会改变它。 类似地, 1in计算独立的, 因为将其转换为计算值仅依赖于“全局知识”,即 1in 等于 96px, 这不能被 CSS 中的任何内容改变或调整。

另一方面, 3em 不是 计算独立的, 因为它依赖于元素(或元素父级)的 font-size 的值。 值也不是 var() 函数,因为它依赖于 自定义属性 的值。

当自定义属性使用特定类型注册时, 该属性的指定值如何转换为计算值的过程由所选类型完全定义, 如 § 2.4 计算值时行为 中所述。

注意: 未来可能会添加注销属性的方法。

注册自定义属性不得以任何方式影响 级联。 不管注册属性指定什么语法, 在解析时它仍然被视为普通的 自定义属性, 准许几乎任何内容。 如果 指定值 对于 注册自定义属性 违反注册语法, 则该属性在计算值时变为无效(因此重置为注册的初始值)。

默认情况下,所有可以解析为标记序列的自定义属性声明都是有效的。 因此,以下样式表的结果:
.thing {
  --my-color: green;
  --my-color: url("not-a-color");
  color: var(--my-color);
}

是将类为 "thing" 的元素的 color 属性设置为 inherit。 第二个 --my-color 声明在解析时覆盖第一个(两者都是有效的), 而在 color 属性中的 var() 引用被发现为 在计算值时无效(因为 url("not-a-color") 不是颜色)。 在 CSS 管道的这个阶段(计算时间), 唯一可用的后备是属性的初始值, 对于颜色而言是 inherit。 尽管有一个有效可用值(green), 但在解析期间由于被 URL 取代而被移除。

如果我们调用:

CSS.registerProperty({
  name: "--my-color",
  syntax: "<color>",
  initialValue: "black",
  inherits: false
});

解析并不会显著改变, 无论注册发生在上面的样式表之前还是之后。 唯一的区别是 --my-color 属性变为 在计算值时无效, 并设置为其初始值 black; 然后 color 被 有效地设置为 black, 而不是在计算值时无效并变为 inherit

4.2. 属性定义 PropertyDefinition 字典

PropertyDefinition 字典表示 作者指定的自定义属性配置选项。 PropertyDefinition 字典包含以下成员:

name, 类型为 DOMString

定义的自定义属性的名称。

syntax, 类型为 DOMString,默认为 "*"

表示此自定义属性如何解析的字符串。

inherits, 类型为 boolean

如果该自定义属性应该沿着 DOM 树继承,则为真;否则为假。

initialValue, 类型为 DOMString

此自定义属性的初始值。

5. 语法字符串

语法字符串 描述 注册的自定义属性接受的值类型。语法字符串由 语法组件名称 组成, 可选地 乘以组合

语法字符串可以解析为 语法定义,其形式为:

  1. 一组 语法组件,每个组件接受在 § 5.1 支持的名称 中指定的值类型,或

  2. 通用语法定义 universal syntax definition (*),接受任何有效的标记流。

注意: 无论指定什么语法,所有自定义属性都接受 CSS-wide 关键字,并适当地处理这些值。

例如,以下都是有效的语法字符串。
"<length>"

接受长度值

"<length> | <percentage>"

接受长度、百分比、百分比计算表达式和长度计算表达式,但不接受包含长度和百分比值组合的计算表达式。

"<length-percentage>"

接受所有 "<length> | <percentage>" 接受的值,以及包含长度和百分比值组合的计算表达式。

"big | bigger | BIGGER"

接受标识符 bigbiggerBIGGER

"<length>+"

接受空格分隔的长度值列表。

"*"

接受任何有效的标记流

注意: 语法字符串的内部语法是 CSS 值定义语法 的子集。预计本规范的未来版本将扩展允许的语法的复杂性,使自定义属性更接近 CSS 属性允许的全部内容。

本章的其余部分描述语法字符串的内部语法。

5.1. 支持的名称

本节定义了 支持的语法组件名称,以及生成的 语法组件 所接受的相应类型。

"<length>"

任何有效的 <length>

"<number>"

<number>

"<percentage>"

任何有效的 <percentage>

"<length-percentage>"

任何有效的 <length><percentage> 值,任何有效的 <calc()> 表达式组合 <length><percentage> 组件。

"<color>"

任何有效的 <color>

"<image>"

任何有效的 <image>

"<url>"

任何有效的 <url>

"<integer>"

任何有效的 <integer>

"<angle>"

任何有效的 <angle>

"<time>"

任何有效的 <time>

"<resolution>"

任何有效的 <resolution>

"<transform-function>"

任何有效的 <transform-function>

"<custom-ident>"

任何有效的 <custom-ident>

任何序列 以标识符开头可以被视为名称,并与 <custom-ident> 生成匹配

该标识符

注意: <custom-ident> 是逐码点比较的; 这与 UA 定义的 CSS 的正常行为不同,后者仅限于 ASCII 并且是 ASCII 不区分大小写。 因此,指定 ident 如 Red 意味着接受精确值 RedredRED 及任何其他大小写变体均不匹配。 建议将 idents 限制为 ASCII,并以小写字母书写, 以符合 CSS 约定。

"<transform-list>"

有效的 <transform-function> 值的列表。注意 "<transform-list>" 是等同于 "<transform-function>+"预乘数据类型名称

注意: 语法字符串 "*" 将产生 通用语法定义,这不是 语法组件。 因此,"*" 可能不能被 乘以与其他东西结合

5.2. “+” 和 “#” 乘数

除了 预乘数据类型名称 之外,任何 语法组件名称 后面可以紧跟一个乘数:

U+002B 加号 (+)

表示一个空格分隔的列表。

U+0023 井号 (#)

表示一个逗号分隔的列表。

"<length>+"

接受一个空格分隔的长度值列表

"<color>#"

接受一个逗号分隔的颜色值列表

注意: 乘数必须紧跟在被乘的 语法组件名称 之后出现。

5.3. “|” 组合符

语法字符串 可以使用 U+007C 竖线 (|) 提供多个 语法组件名称。这样的语法字符串将导致生成一个 语法定义 ,其中包含多个 语法 组件

当一个 语法 定义 具有多个 语法组件 时, 用于解析 CSS 值时,语法组件将按指定顺序匹配。

注意: 即,给定语法字符串 "red | <color>", 将匹配值 red 解析为标识符, 而匹配值 blue 将 解析为 <color>

"<length> | auto"

接受一个长度或 auto

"foo | <color># | <integer>"

接受 foo,一个颜色值的逗号分隔列表,或一个整数

5.4. 解析语法字符串

5.4.1. 定义

数据类型 名称

一系列 代码点,由一个 U+003C 小于号 (<) 开头, 后接零个或多个 标识符代码点,并以 U+003E 大于号 (>) 结束。

预乘数据类型名称

一个 数据类型名称 代表另一个 语法组件,并且已包含一个 乘数

语法 组件

一个对象,由 语法组件名称 和一个可选的 乘数 组成。

语法 组件名称

一系列 代码点,它可以是 数据类型名称, 或一个能够产生 <custom-ident> 的序列。

语法 定义

一个对象,由一系列 语法组件 组成。

通用语法定义

一个特殊的语法定义,接受任何有效的令牌流。

5.4.2. 消耗语法定义

本节描述如何从一个字符串 string消耗语法定义。 它要么产生一个带有多个语法组件语法定义,要么产生通用语法定义
  1. 去掉字符串 string的前后ASCII空格。

  2. 如果 string长度为0, 返回失败。

  3. 如果 string长度 为1,且唯一的代码点为U+002A ASTERISK (*), 返回通用语法定义

  4. stream成为从 string代码点创建的 输入流, 按照[css-syntax-3]中指定的预处理。 让 definition 成为一个最初为空的列表,其中包含语法组件

  5. 从流中消耗一个语法组件。 如果返回失败,返回失败; 否则,将返回值追加definition

    stream 中消耗尽可能多的空格

    消耗 stream中的下一个输入代码点

    EOF

    返回 definition

    U+007C VERTICAL LINE (|)

    重复步骤5。

    其他任何情况:

    返回失败。

5.4.3. 消耗语法组件

从一组代码点流中 消耗语法组件

stream 中消耗尽可能多的空格

component 成为一个新的语法组件,其namemultiplier最初为空。

消耗 stream中的下一个输入代码点

U+003C LESS-THAN SIGN (<)

stream 中消耗数据类型名称。 如果返回一个字符串,则将 componentname 设置为返回值。 否则,返回失败。

标识符开始代码点
U+005C REVERSE SOLIDUS (\)

如果流以标识符序列开头重新消费当前输入代码点,然后stream 中消耗标识符序列, 并将 componentname 设置为返回值。 否则返回失败。

如果 componentname解析<custom-ident>,返回失败。

其他任何情况

返回失败。

如果 componentname预乘数据类型名称, 返回 component

如果 stream中的下一个输入代码点为U+002B PLUS SIGN (+)或U+0023 NUMBER SIGN (#), 消耗下一个输入代码点, 并将 componentmultiplier 设置为当前输入代码点

返回 component

5.4.4. 消耗数据类型名称

从一组代码点流中 消耗数据类型名称

注意:此算法假设已经从流中消耗了一个 U+003C LESS-THAN SIGN (<) 代码点

name 最初为一个包含单个 U+003C LESS-THAN SIGN (<) 代码点字符串

重复消耗下一个输入代码点

U+003E GREATER-THAN SIGN (>)

代码点附加到 name。 如果 name支持的语法组件名称, 返回 name。 否则返回失败。

标识符代码点

代码点附加到 name

其他任何情况

返回失败。

6. CSSOM

为注册自定义属性指定的值在计算值时才会被解释。这意味着只有检索计算值的 API 会受到影响。其他 API 必须忽略相关的 [[registeredPropertySet]] 插槽和 Document, 并将所有自定义属性视为未注册。

6.1. CSS CSSPropertyRule 接口

CSSPropertyRule 接口表示一个@property 规则。

[Exposed=Window]
interface CSSPropertyRule : CSSRule {
  readonly attribute CSSOMString name;
  readonly attribute CSSOMString syntax;
  readonly attribute boolean inherits;
  readonly attribute CSSOMString? initialValue;
};
name, 类型为 CSSOMString, 只读
@property规则相关的自定义属性名称。
syntax, 类型为 CSSOMString, 只读
@property相关的语法,完全按照指定内容。
inherits, 类型为 boolean, 只读
@property规则相关的继承描述符。
initialValue, 类型为 CSSOMString, 只读,可能为空
@property规则相关的初始值,可能不存在。
序列化一个 CSSPropertyRule,返回以下内容的连接:
  1. 字符串 "@property" 后跟一个空格(U+0020)。

  2. 对规则名称执行序列化标识符的结果,后跟一个空格(U+0020)。

  3. 字符串 "{ ",即一个左大括号(U+007B),后跟一个空格(U+0020)。

  4. 字符串 "syntax:",后跟一个空格(U+0020)。

  5. 对规则的语法执行序列化字符串的结果,后跟一个分号(U+003B), 后跟一个空格(U+0020)。

  6. 字符串 "inherits:",后跟一个空格(U+0020)。

  7. 对于规则的inherits属性,根据属性值的不同,以下任意一种:

    true

    字符串 "true" 后跟一个分号(U+003B),后跟一个空格(U+0020)。

    false

    字符串 "false" 后跟一个分号(U+003B),后跟一个空格(U+0020)。

  8. 如果规则的initial-value存在,则执行以下子步骤:

    1. 字符串 "initial-value:"

    2. 对规则的initial-value执行序列化CSS值,后跟一个分号(U+003B),后跟一个空格(U+0020)。

  9. 一个右大括号(U+007D)。

6.2. CSSStyleValue 具体化

具体化注册的自定义属性值,给定属性property语法定义 syntax,执行以下步骤:

对于指定值,具体化一组组件值并返回结果。

对于计算值:

  1. 如果值是<length><integer><number><angle><time><resolution><percentage><length-percentage>具体化一个数值并返回结果。

  2. 如果值是<transform-function>具体化一个<transform-function>并返回结果。

  3. 如果值是<transform-list>具体化一个<transform-list>并返回结果。

  4. 如果值是一个<image>,具体化一个CSSImageValue并返回结果。

  5. 如果值是一个标识符具体化一个标识符并返回结果。

  6. 如果syntax通用语法定义具体化一组组件值并返回结果。

  7. 否则,作为CSSStyleValue具体化,其中[[associatedProperty]] 内部槽设置为property,并返回结果。

7. 示例

7.1. 示例 1: 使用自定义属性添加动画行为

<script>
CSS.registerProperty({
  name: "--stop-color",
  syntax: "<color>",
  inherits: false,
  initialValue: "rgba(0,0,0,0)"
});
</script>

<style>
.button {
  --stop-color: red;
  background: linear-gradient(var(--stop-color), black);
  transition: --stop-color 1s;
}

.button:hover {
  --stop-color: green;
}
</style>

7.2. 示例 2: 使用 @property 注册属性

<script>
  CSS.paintWorklet.addModule('circle.js');
</script>
<style>
  @property --radius {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
  }

  div {
    width: 100px;
    height: 100px;
    --radius: 10px;
    background: paint(circle);
    transition: --radius 1s;
  }

  div:hover {
    --radius: 50px;
  }
</style>
<div></div>
// circle.js
registerPaint('circle', class {
    static get inputProperties() { return ['--radius']; }
    paint(ctx, geom, properties) {
      let radius = properties.get('--radius').value;
      ctx.fillStyle = 'black';
      ctx.beginPath();
      ctx.arc(geom.width / 2, geom.height / 2, radius, 0, 2 * Math.PI);
      ctx.fill();
    }
});

8. 安全考虑

这些特性没有已知的安全问题。

9. 隐私考虑

这些特性没有已知的隐私问题。

10. 变更

10.1. 自2020年10月13日的工作草案以来的变更

/* 到2024年3月20日 */

一致性

文档约定

一致性要求通过描述性声明和RFC 2119术语的组合来表达。本文件的规范部分中的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”应根据RFC 2119进行解释。然而,为了可读性,这些词在本规范中并不全以大写字母出现。

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

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

这是一个信息性示例的例子。

信息性注释以“注释”开头,并用class="note"与规范文本分开,如下所示:

注意,这是一个信息性注释。

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

一致性类别

本规范的一致性定义为三种一致性类别:

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

如果样式表中使用本模块定义的语法的所有语句都是根据通用CSS语法和本模块中定义的每个特性的单独语法有效的,则样式表符合本规范。

如果渲染器在解释样式表时符合适当的规范,并支持本规范定义的所有特性,正确解析它们并相应地渲染文档,则渲染器符合本规范。然而,由于设备限制,用户代理无法正确渲染文档并不使其不符合规范。(例如,用户代理不需要在单色显示器上渲染颜色。)

如果创作工具编写的样式表在语法上符合通用CSS语法和本模块中每个特性的单独语法,并满足本模块中描述的样式表的所有其他一致性要求,则创作工具符合本规范。

部分实现

为了让作者能够利用向前兼容的解析规则分配备用值,CSS渲染器必须将任何没有可用支持级别的@规则、属性、属性值、关键字和其他语法构造视为无效(并视为适当的忽略)。特别是,用户代理不得选择性地忽略不支持的组件值,并在单个多值属性声明中尊重支持的值:如果任何值被视为无效(因为不支持的值必须是),CSS要求整个声明被忽略。

不稳定和专有特性的实现

为了避免与未来稳定的CSS特性发生冲突,CSS工作组建议遵循最佳实践来实现不稳定特性和专有扩展

非实验性实现

一旦规范达到候选推荐阶段,可以进行非实验性实现,实施者应发布任何能够根据规范正确实现的CR级特性的未加前缀的实现。

为了建立和维护CSS在实现中的互操作性,CSS工作组请求非实验性的CSS渲染器在发布任何CSS特性的未加前缀的实现之前,向W3C提交实现报告(如有必要,还需提交用于该实现报告的测试用例)。提交给W3C的测试用例将受到CSS工作组的审查和更正。

有关提交测试用例和实现报告的更多信息,请访问CSS工作组网站:https://www.w3.org/Style/CSS/Test/。如有疑问,请联系public-css-testsuite@w3.org邮件列表。

索引

本规范定义的术语

通过引用定义的术语

参考文献

规范性参考文献

[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS 层叠和继承第 4 版. 2022 年 1 月 13 日. CR. URL: https://www.w3.org/TR/css-cascade-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠和继承第 5 版. 2022 年 1 月 13 日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠和继承第 6 版. 2023 年 3 月 21 日. WD. URL: https://www.w3.org/TR/css-cascade-6/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS 颜色模块第 4 版. 2022 年 11 月 1 日. CR. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; 等. CSS 颜色模块第 5 版. 2022 年 6 月 28 日. WD. URL: https://www.w3.org/TR/css-color-5/
[CSS-CONDITIONAL-3]
David Baron; Elika Etemad; Chris Lilley. CSS 条件规则模块第 3 版. 2022 年 1 月 13 日. CR. URL: https://www.w3.org/TR/css-conditional-3/
[CSS-FONTS-4]
Chris Lilley. CSS 字体模块第 4 版. 2024 年 2 月 1 日. WD. URL: https://www.w3.org/TR/css-fonts-4/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS 图片模块第 3 版. 2023 年 12 月 18 日. CR. URL: https://www.w3.org/TR/css-images-3/
[CSS-IMAGES-4]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS 图片模块第 4 版. 2023 年 2 月 17 日. WD. URL: https://www.w3.org/TR/css-images-4/
[CSS-SCOPING-1]
Tab Atkins Jr.; Elika Etemad. CSS 范围模块第 1 版. 2014 年 4 月 3 日. WD. URL: https://www.w3.org/TR/css-scoping-1/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS 语法模块第 3 版. 2021 年 12 月 24 日. CR. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-TRANSFORMS-1]
Simon Fraser; 等. CSS 变换模块第 1 版. 2019 年 2 月 14 日. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSS-TYPED-OM-1]
Shane Stephens; Tab Atkins Jr.; Naina Raisinghani. CSS 类型 OM 第 1 版. 2018 年 4 月 10 日. WD. URL: https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值和单位模块第 4 版. 2023 年 12 月 18 日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VARIABLES]
Tab Atkins Jr.. CSS 自定义属性用于层叠变量模块第 1 版. 2022 年 6 月 16 日. CR. URL: https://www.w3.org/TR/css-variables-1/
[CSS22]
Bert Bos. 层叠样式表第 2 版修订版 2 (CSS 2.2) 规范. 2016 年 4 月 12 日. WD. URL: https://www.w3.org/TR/CSS22/
[CSS3-VALUES]
Tab Atkins Jr.; Elika Etemad. CSS 值和单位模块第 3 版. 2022 年 12 月 1 日. CR. URL: https://www.w3.org/TR/css-values-3/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型 (CSSOM). 2021 年 8 月 26 日. WD. URL: https://www.w3.org/TR/cssom-1/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; 等. HTML 标准. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. 基础标准. 现行标准. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC 中指示要求级别的关键词. 1997 年 3 月. 当前最佳实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEB-ANIMATIONS-1]
Brian Birtles; 等. Web 动画. 2023 年 6 月 5 日. WD. URL: https://www.w3.org/TR/web-animations-1/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行标准. URL: https://webidl.spec.whatwg.org/

参考文献

[CSS-LAYOUT-API-1]
Greg Whitworth; 等. CSS 布局 API 1 级. 2018 年 4 月 12 日. WD. URL: https://www.w3.org/TR/css-layout-api-1/
[CSS-PAINT-API-1]
Ian Kilpatrick; Dean Jackson. CSS 绘画 API 1 级. 2021 年 12 月 16 日. CR. URL: https://www.w3.org/TR/css-paint-api-1/
[CSS-SHADOW-PARTS-1]
Tab Atkins Jr.; Fergal Daly. CSS 阴影部件. 2018 年 11 月 15 日. WD. URL: https://www.w3.org/TR/css-shadow-parts-1/
[CSS3-ANIMATIONS]
David Baron; 等. CSS 动画 1 级. 2023 年 3 月 2 日. WD. URL: https://www.w3.org/TR/css-animations-1/
[CSS3-TRANSITIONS]
David Baron; 等. CSS 过渡. 2018 年 10 月 11 日. WD. URL: https://www.w3.org/TR/css-transitions-1/

属性索引

未定义任何属性。

@property 描述符

名称 初始
inherits true | false 不适用(见正文)
initial-value <declaration-value>? 保证无效值(但见正文)
syntax <string> 不适用(见正文)

IDL 索引

dictionary PropertyDefinition {
  required DOMString name;
           DOMString syntax       = "*";
  required boolean   inherits;
           DOMString initialValue;
};

partial namespace CSS {
  undefined registerProperty(PropertyDefinition definition);
};

[Exposed=Window]
interface CSSPropertyRule : CSSRule {
  readonly attribute CSSOMString name;
  readonly attribute CSSOMString syntax;
  readonly attribute boolean inherits;
  readonly attribute CSSOMString? initialValue;
};

MDN

CSS/registerProperty_static

In all current engines.

Firefoxpreview+Safari16.4+Chrome78+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSPropertyRule/inherits

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSPropertyRule/initialValue

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSPropertyRule/name

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSPropertyRule/syntax

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSPropertyRule

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@property/inherits

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@property/initial-value

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@property/syntax

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@property

In all current engines.

Firefoxpreview+Safari16.4+Chrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?