CSS 层叠变量自定义属性模块第 1 级

W3C 候选推荐标准快照,

关于此文档的更多细节
此版本
https://w3org.cn/TR/2022/CR-css-variables-1-20220616/
最新发布版本
https://w3org.cn/TR/css-variables-1/
编辑草案
https://drafts.csswg.org/css-variables/
历史版本
历史
https://w3org.cn/standards/history/css-variables-1
实现报告
https://wpt.fyi/results/css/css-variables
测试套件
http://test.csswg.org/suites/css-variables-1_dev/nightly-unstable/
https://wpt.fyi/results/css/css-variables/
反馈
CSS 工作组问题仓库
编辑
Tab Atkins Jr. (Google)
建议编辑此规范
GitHub 编辑器

摘要

本模块引入了层叠变量作为一种新的原生值类型,可被所有 CSS 属性接受,并引入了用于定义它们的自定义属性。

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

关于本文档

本部分描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新版本可在 W3C 技术报告索引(https://w3org.cn/TR/)中找到。

本文档由 CSS 工作组推荐标准轨道发布,作为候选推荐标准快照。发布为候选推荐标准并不意味着获得 W3C 及其成员的认可。候选推荐标准快照已获得广泛审阅,旨在收集实现经验,并有工作组成员对实现的免版税许可承诺。本文档旨在成为 W3C 推荐标准;它将至少保留为候选推荐标准至 以收集额外反馈。

请通过在 GitHub 上提交议题(首选)发送反馈,并在标题中包含规范代码“css-variables”,格式如下:“[css-variables] …评论摘要…”。所有议题和评论均已存档。此外,也可以发送反馈至(已存档的)公共邮件列表 www-style@w3.org

本文档受 2021 年 11 月 2 日版 W3C 流程文档管辖。

本文档由在 W3C 专利政策下运作的组织制作。W3C 维护一份与该组织交付成果相关的 公开专利披露列表;该页面还包含披露专利的说明。任何知悉其认为包含 必要权利要求 的专利的个人,必须按照 W3C 专利政策第 6 节披露该信息。

1. 简介

本节不具有规范性。

大型文档或应用程序(甚至小型项目)可能包含相当多的 CSS。CSS 文件中的许多值通常是重复数据;例如,一个网站可能建立了一种配色方案,并在全站范围内重复使用三到四种颜色。修改这些数据可能既困难又容易出错,因为它们分散在 CSS 文件中(甚至可能分布在多个文件中),且可能无法通过“查找与替换”轻松处理。

本模块引入了一系列由作者定义的自定义属性,统称为自定义属性,允许作者为自定义名称的属性分配任意值;同时引入了 var() 函数,允许作者在文档其他地方的属性中使用这些值。这使得阅读大型文件变得更加容易,因为看似随意的值现在有了信息丰富的名称;同时也使得编辑此类文件变得更加简单且不易出错,因为只需在自定义属性中修改一次值,更改就会自动传播到该变量的所有使用处。

1.1. 值定义

本规范遵循 CSS 属性定义约定[CSS2]),使用 值定义语法[CSS-VALUES-3])。本规范未定义的值类型在 CSS Values & Units [CSS-VALUES-3] 中定义。与其他 CSS 模块的组合可能会扩展这些值类型的定义。

除了定义中列出的属性特定值外,本规范中定义的所有属性也都接受 CSS 全局关键字 作为其属性值。为了可读性,未明确重复列出。

2. 定义自定义属性:--* 属性家族

本规范定义了一组开放式的属性,称为自定义属性,除其他用途外,它们还用于定义 var() 函数的替代值

名称--*
<declaration-value>?
初始值 保证无效值
应用于 所有元素和所有伪元素(包括具有限制属性列表的元素)
可继承
百分比 不可用
计算值 代入变量后的指定值,或保证无效值
规范顺序 按语法
动画类型 离散 (discrete)

用户代理应在所有介质(包括非可视介质)上支持此属性。

任何名称以两个连字符(U+002D HYPHEN-MINUS)开头的属性都是自定义属性,例如 --foo<custom-property-name> 产生式对应于此:它定义为任何 <dashed-ident>(以两个连字符开头的有效标识符),但 -- 本身除外,它是保留给 CSS 未来使用的。自定义属性仅供作者和用户使用;CSS 永远不会赋予它们超出本文所述的含义。

测试
自定义属性定义变量,通过 var() 标记法引用,可用于多种目的。例如,一个设计中始终使用少量颜色的页面可以将颜色存储在自定义属性中,并使用变量来使用它们。
:root {
  --main-color: #06c;
  --accent-color: #006;
}
/* The rest of the CSS file */
#foo h1 {
  color: var(--main-color);
}

这种命名为颜色提供了助记符,防止了颜色代码中难以察觉的拼写错误,并且如果主题颜色发生变化,只需将更改聚焦在一个简单的地方(自定义属性值),而无需对网页中的所有样式表进行多次编辑。

与其他 CSS 属性不同,自定义属性名称不是 ASCII 大小写不敏感的。相反,自定义属性名称仅在彼此完全相同时才相等。

测试
虽然 --foo--FOO 都是合法的,但它们是不同的属性——使用 var(--foo) 将引用前者,而使用 var(--FOO) 将引用后者。

也许更令人惊讶的是,--foó--foó 是不同的属性。前者由 U+00F3(拉丁小写字母 O 带锐音符)拼写,而后者由 ASCII “o” 后跟 U+0301(组合锐音符)拼写,且“完全相同”关系使用直接的码点对码点比较来确定两个字符串是否相等,以避免 Unicode 规范化和区域特定排序带来的复杂性和陷阱。

操作系统、键盘或输入法有时会使用不同的码点序列对视觉上相同的文本进行编码。建议作者选择能避免潜在混淆的变量名称,或使用转义等手段来确保外观相似的序列是相同的。示例见 [CHARMOD-NORM] 第 2.3 节。

维护以下 CSS 的开发者可能会困惑为什么测试补丁是红色的。
--fijord: red;
--fijord: green;
--fijord: blue;

.test {
  background-color: var(--fijord);
}

原因是第一个自定义属性使用了字符序列:拉丁小写字母 F + 拉丁小写字母 I + 拉丁小写字母 J;第二个外观相同的属性使用了字符序列:拉丁小写字母 F + 拉丁小写连字 IJ,而第三个使用了字符序列:拉丁小写连字 FI + 拉丁小写字母 J。

因此该 CSS 包含三个不同的自定义属性,其中两个是未使用的。

自定义属性不会all 属性重置。我们将来可能会定义一个重置所有变量的属性。

CSS 宽关键词可在自定义属性中使用,其含义与在任何其他属性中相同。

测试

注意:也就是说,它们在层叠值时正常解释,并没有作为自定义属性的值被保留,因此不会被相应的变量替换。

注意:虽然本模块重点在于使用自定义属性var() 函数来创建“变量”,但它们也可以作为实际的自定义属性使用,由脚本解析并操作。预计 CSS 扩展规范 [CSS-EXTENSIONS] 将扩展这些用例并使其更易于实现。

自定义属性是普通属性,因此它们可以声明在任何元素上,通过正常的继承和层叠规则解析,可以使用 @media 和其他条件规则进行条件化,可以在 HTML 的 style 属性中使用,可以通过 CSSOM 读取或设置等。

测试

值得注意的是,它们甚至可以过渡或动画化,但由于 UA 无法解释其内容,它们始终使用任何其他无法智能插值的成对值所采用的“在 50% 处翻转”的行为。然而,任何在 @keyframes 规则中使用的自定义属性都会变得受动画影响,这会影响在动画属性中通过 var() 函数引用它时的处理方式。

测试

受动画影响是“传染性的”:引用了受动画影响属性的自定义属性也会变得受动画影响

此样式规则
:root {
  --header-color: #06c;
}

在根元素上声明了一个名为 --header-color自定义属性,并为其分配了值“#06c”。该属性随后被继承到文档其余部分的元素中。其值可以通过 var() 函数引用。

h1 { background-color: var(--header-color); }

前述规则等同于编写 background-color: #06c;,只是变量名使颜色的来源更清晰,并且如果文档中的其他元素使用了 var(--header-color),则可以通过更改根元素上的 --header-color 属性来一次性更新所有使用处。

如果自定义属性被声明多次,标准层叠规则将有助于解析它。变量总是从同一元素上相关自定义属性的计算值中提取。
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }

<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id='alert'>
  While I got red set directly on me!
  <p>I’m red too, because of inheritance!</p>
</div>
自定义属性用法的一个现实示例是轻松地将字符串与它们的使用位置分离,以辅助国际化维护。
:root,
:root:lang(en) {--external-link: "external link";}
:root:lang(el) {--external-link: "εξωτερικός σύνδεσμος";}

a[href^="http"]::after {content: " (" var(--external-link) ")"}

变量声明甚至可以保留在单独的文件中,以使翻译的维护更简单。

2.1. 自定义属性值语法

允许的自定义属性语法极其宽松。<declaration-value> 产生式匹配任何一个或多个令牌序列,只要该序列不包含 <bad-string-token><bad-url-token>、不匹配的 <)-token><]-token><}-token>,或者顶层的 <semicolon-token> 令牌或值为“!”的 <delim-token> 令牌。

测试

此外,如果自定义属性的值包含 var() 引用,该 var() 引用必须根据指定的 var() 语法有效。否则,该自定义属性无效,必须忽略。

注意:此定义连同通用 CSS 语法规则,暗示自定义属性值从不包含不匹配的引号或括号,因此在重新序列化时,对较大的语法结构(如封闭的样式规则)没有任何影响。

注意:自定义属性可以包含尾随的 !important,但这会被 CSS 解析器自动从属性值中移除,并使该自定义属性在 CSS 层叠中变得“重要”。换句话说,对顶层“!”字符的禁止并不妨碍 !important 的使用,因为 !important 在语法检查发生前已被移除。

测试
例如,以下是一个有效的自定义属性
--foo: if(x > 5) this.width = 10;

虽然这个值作为变量显然没用(因为它在任何正常属性中都是无效的),但它可能被 JavaScript 读取和操作。

自定义属性的值,以及代入自定义属性中的 var() 函数的值,是大小写敏感的,且必须保留其作者给定的原始大小写。(许多 CSS 值是 ASCII 大小写不敏感的,用户代理可以通过将它们“规范化”为单一大小写来利用这一点,但自定义属性不允许这样做。)

测试
由于自定义属性可以包含任何内容,因此在它们被 var() 代入已知属性之前,没有通用的方法来理解其中的内容。为了不让它们在某些情况下部分解析而在其他情况下不解析,它们被完全保持为未解析状态;它们是一串散布着 var() 函数的CSS 令牌流。

这带来了一些连锁影响。例如,CSS 中的相对 URL 是针对该值所在样式表的基 URL 进行解析的。然而,如果类似 --my-image: url(foo.jpg); 的自定义属性出现在 "/a/style.css" 样式表中,它不会立即解析为绝对 URL;如果该变量稍后在另一个 "/b/style.css" 样式表中被用作 background: var(--my-image);,它将在那个点解析为 "/b/foo.jpg"

2.2. 保证无效值

自定义属性的初始值是一个保证无效值。正如 § 3 使用层叠变量:var() 标记法中所定义,使用 var() 来代入以其为值的自定义属性,会使引用它的属性变得在计算值时无效

此值序列化为空字符串,但实际上将空值写入自定义属性(如 --foo: ;)是一个有效的(空)值,而非保证无效值。如果由于某种原因想要手动将变量重置为保证无效值,可以使用关键字 initial 来实现。

2.3. 解决依赖循环

自定义属性几乎完全保持未求值状态,除了它们允许并求值其值中的 var() 函数。这可能会产生循环依赖,其中自定义属性使用引用自身的 var(),或者两个或多个自定义属性各自尝试引用对方。

对于每个元素,创建一个有向依赖图,包含每个自定义属性的节点。如果自定义属性 prop 的值包含一个引用属性 varvar() 函数(包括在 var() 的回退参数中),则在 propvar 之间添加一条边。边可能从自定义属性指向其自身。

如果依赖图中存在循环,则循环中的所有自定义属性都是在计算值时无效的。

测试

注意:参与依赖循环的已定义属性,要么其值中最终包含无效变量(从而变得在计算值时无效),要么定义了它们自己的循环处理方式(如 font-size 使用 em 值)。它们不会像自定义属性那样计算为保证无效值

此示例展示了一个安全使用变量的自定义属性
:root {
  --main-color: #c06;
  --accent-background: linear-gradient(to top, var(--main-color), white);
}

--accent-background 属性(以及任何其他使用 var(--main-color) 的属性)将在 --main-color 属性更改时自动更新。

另一方面,此示例展示了一个变量间相互依赖的无效实例
:root {
  --one: calc(var(--two) + 20px);
  --two: calc(var(--one) - 20px);
}

--one--two 现在都是在计算值时无效的,并且计算为保证无效值而非长度。

需要特别注意的是,自定义属性在计算值时解析其值中的任何 var() 函数,这发生在继承值之前。通常,循环依赖仅在同一元素上的多个自定义属性相互引用时发生;在元素树中较高位置的元素上定义的自定义属性永远不会导致与元素树中较低位置的元素上定义的属性产生循环引用。

测试
例如,在以下结构中,这些自定义属性存在循环,且都定义了有效的变量
<one><two><three /></two></one>
<style>
one   { --foo: 10px; }
two   { --bar: calc(var(--foo) + 10px); }
three { --foo: calc(var(--bar) + 10px); }
</style>

<one> 元素为 --foo 定义了一个值。<two> 元素继承此值,并额外使用 foo 变量为 --bar 分配了一个值。最后,<three> 元素在变量替换之后继承 --bar 值(换句话说,它看到的值是 calc(10px + 10px)),然后根据该值重新定义 --foo。由于它继承的 --bar 值不再包含对 <one> 上定义的 --foo 属性的引用,因此使用 var(--bar) 变量定义 --foo 并非循环,实际上定义了一个最终(在普通属性中作为变量引用时)解析为 30px 的值。

3. 使用层叠变量:var() 标记法

自定义属性的值可以通过 var() 函数代入另一个属性的值中。var() 的语法为

var() = var( <custom-property-name> , <declaration-value>? )
测试

@supports


作为通常 逗号省略规则 的一个例外,该规则要求在不分隔值时省略逗号,在 var() 中,必须将一个后面没有任何内容的裸逗号视为有效,表示一个空的回退值。

测试

注意:也就是说,var(--a,) 是一个有效的函数,它指定如果 --a 自定义属性无效或缺失,则应将 var() 替换为空。

var() 函数可用于元素中任何属性的值的任何部分。 var() 函数不能用作属性名称、选择器,或除属性值之外的任何其他内容。(这样做通常会产生无效语法,或者产生一个其含义与变量无关的值。)

测试
例如,以下代码错误地尝试使用变量作为属性名称
.foo {
  --side: margin-top;
  var(--side): 20px;
}

等同于设置 margin-top: 20px;。相反,第二个声明因具有无效的属性名称而被直接作为语法错误丢弃。

函数的第一个参数是要替换的 自定义属性 的名称。函数的第二个参数(如果提供)是一个回退值,当所引用的 自定义属性 的值为 保证无效值 时,该回退值将作为替换值使用。

测试

注意:回退值的语法与 自定义属性 一样,允许使用逗号。例如,var(--foo, red, blue) 定义了一个 red, blue 的回退值;也就是说,第一个逗号和函数末尾之间的任何内容都被视为回退值。

回退值允许进行某些类型的防御性编码。例如,作者可以创建一个旨在包含在更大应用程序中的组件,并使用变量来对其进行样式设置,以便大型应用程序的作者能够轻松地为该组件设置主题以匹配应用程序的其余部分。

没有回退时,应用程序作者必须为您组件使用的每个变量提供一个值。有了回退,组件作者可以提供默认值,这样应用程序作者只需要为他们想要覆盖的变量提供值。

/* In the component’s style: */
.component .header {
  color: var(--header-color, blue);
}
.component .text {
  color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
  --text-color: #080;
  /* header-color isn’t set,
     and so remains blue,
     the fallback value */
}

如果一个属性包含一个或多个 var() 函数,且这些函数在语法上是有效的,则必须假定整个属性的语法在解析时是有效的。只有在计算值时,即在 var() 函数被 替换 之后,才会进行语法检查。

测试

要在属性值中 替换 var()

  1. 如果 var() 函数的第一个参数所命名的 自定义属性动画污染的,并且 var() 函数被用于一个 不可动画的 属性中,则在算法的剩余部分中将该 自定义属性 视为具有其初始值。
  2. 如果 var() 函数的第一个参数所命名的 自定义属性 的值不是初始值,则用相应 自定义属性 的值替换 var() 函数。
  3. 否则,如果 var() 函数具有作为其第二个参数的回退值,则用回退值替换 var() 函数。如果回退中存在任何 var() 引用,也请对它们进行 替换
  4. 否则,包含 var() 函数的属性在 计算值时无效

    注意:其他事项也可能使属性在 计算值时无效

测试

CSSOM(CSS 对象模型)


请注意,var() 替换 发生在 CSS 标记 [css-syntax-3] 的级别,而不是文本级别;您不能构建一个部分由变量提供的单个标记
.foo {
  --gap: 20;
  margin-top: var(--gap)px;
}

等同于设置 margin-top: 20px;(一个长度)。相反,它等同于 margin-top: 20 px;(一个数字后跟一个标识符),这对于 margin-top 属性来说只是一个无效值。但是请注意,calc() 可以用于有效地实现同样的事情,如下所示

.foo {
  --gap: 20;
  margin-top: calc(var(--gap) * 1px);
}
测试

var() 函数在计算值时进行 替换。如果一个声明在所有 var() 函数被替换后不符合其声明的语法,则该声明在 计算值时无效

测试

如果一个声明在所有 var() 函数被替换后,仅包含一个 CSS 范围内的关键字(以及可能的空白字符),则其值确定方式就像该关键字一直作为其 指定值 一样。

测试
例如,以下用法从语法角度来看没问题,但在变量被替换时会导致无意义的结果
:root { --looks-valid: 20px; }
p { background-color: var(--looks-valid); }

由于 20px 对于 background-color 来说是一个无效值,此属性实例计算为 transparentbackground-color 的初始值)而不是其他值。

如果该属性是默认继承的属性(例如 color),它将计算为继承的值,而不是初始值。

虽然 var() 函数无法从 自定义属性 本身获取 CSS 范围内的关键字——如果您尝试指定它,例如 --foo: initial;,它只会触发自定义属性的 显式默认——但它可以在其回退中包含一个 CSS 范围内的关键字
p { color: var(--does-not-exist, initial); }

在上面的代码中,如果 --does-not-exist 属性不存在或在 计算值时无效,则 var() 将改为替换为 initial 关键字,使属性的行为就像它最初是 color: initial 一样。这将使其采用文档的初始 color 值,而不是默认继承,如果没有任何回退,本应如此。

3.1. 无效变量

自定义属性 的值为 保证无效值 时,var() 函数不能将其用于替换。尝试这样做会使声明在 计算值时无效,除非指定了有效的回退。

如果声明包含一个引用 自定义属性 且值为 保证无效值var()(如上所述),或者它使用有效的 自定义属性,但属性值在替换其 var() 函数后无效,则该声明可能 在计算值时无效。发生这种情况时,计算值是以下之一,具体取决于属性的类型

属性是一个非注册的 自定义属性
属性是一个具有 通用语法注册自定义属性

计算值为 保证无效值

否则

属性的继承值或其初始值,取决于属性是否被继承,就好像属性的值已被指定为 unset 关键字一样。

测试
例如,在以下代码中
:root { --not-a-color: 20px; }
p { background-color: red; }
p { background-color: var(--not-a-color); }

<p> 元素将具有透明背景(background-color 的初始值),而不是红色背景。如果 自定义属性 本身未设置,或包含无效的 var() 函数,也会发生同样的情况。

请注意这与如果作者直接在样式表中编写 background-color: 20px 的情况有何不同——那将是一个普通的语法错误,会导致规则被丢弃,因此会使用 background-color: red 规则。

注意:存在 在计算值时无效 的概念,是因为变量不能像其他语法错误那样“尽早失败”,所以当用户代理意识到属性值无效时,它已经丢弃了其他级联值。

3.2. 简写属性中的变量

在将 简写属性 解析为其组件长属性,以及从其组件长属性序列化 简写属性 时,var() 函数会产生一些复杂性。

如果 简写属性 的值中包含 var() 函数,则与其关联的 长属性 必须填充一个特殊的、对作者不可见的 待替换值,该值指示简写包含一个变量,因此在变量被 替换 之前,无法确定长属性的值。

然后,该值必须正常级联。在计算值时,即在 var() 函数最终被替换后,必须解析简写,并在此点赋予长属性适当的值。

测试

注意:当简写属性在没有 var() 的情况下编写时,它会在解析时被解析并分离为其组件 长属性;然后长属性参与 级联,而 简写属性 则或多或少被丢弃。然而,当简写包含 var() 时,则无法做到这一点,因为 var() 可以被任何内容替换。

待替换值 必须序列化为空字符串(如果 API 允许观察它们)。

测试

简写属性 通过收集其组件 长属性 的值并合成为一个能解析为同一组值的字符串来序列化。

如果给定 简写 的所有组件 长属性 都是来自同一原始简写值的 待替换值,则 简写属性 必须序列化为该原始(包含 var())值。

否则,如果给定 简写 的任何组件 长属性待替换值,或者其自身包含尚未替换的 var() 函数,则 简写属性 必须序列化为空字符串。

3.3. 安全处理过长的变量

如果实现不当,var() 函数可用于“十亿笑话攻击”的变体

.foo {
  --prop1: lol;
  --prop2: var(--prop1) var(--prop1);
  --prop3: var(--prop2) var(--prop2);
  --prop4: var(--prop3) var(--prop3);
  /* etc */
}

在这个简短的示例中,--prop4 的计算值为 lol lol lol lol lol lol lol lol,包含 8 个原始 lol 的副本。在此基础上每增加一个级别都会使标识符的数量翻倍;将其扩展到仅仅 30 个级别(手动几分钟的工作量),就会使 --prop30 包含 近十亿个 标识符实例。

为了避免此类攻击,UA 必须对 var() 函数展开成的标记流的允许长度实施 UA 定义的限制。如果 var() 展开后的标记流超过此限制,它反而会使它正在展开的属性在 计算值时无效

测试

本规范未定义应实施何种长度限制。然而,由于自定义属性存在包含一千字节或更多文本的有效用例,因此建议将限制设置得相对较高。

注意:UA 因资源限制而允许违反标准的一般原则在这里仍然普遍适用;UA 可能单独对它们能支持的自定义属性的长度或能支持的标识符的大小有限制。本节特别指出此攻击是因为其由来已久,并且它可以在所有片段初看时都似乎不大,但仍能被执行。

4. API

所有 自定义属性 声明 都设置了 大小写敏感标志

测试

注意:自定义属性不会以驼峰命名形式出现在 CSSStyleDeclaration 对象上,因为它们的名称可能同时包含大写和小写字母,这表示不同的自定义属性。自动驼峰转换所执行的那种文本转换与此不兼容。它们仍然可以通过 getPropertyValue() 等通过其正确名称进行访问。

4.1. 序列化自定义属性

自定义属性名称必须序列化为作者提供的确切代码点序列,包括不改变大小写。

注意:对于非自定义属性,属性名称限制在 ASCII 范围内并且是 ASCII 大小写不敏感的,因此实现通常将名称小写化进行序列化。

自定义属性 的指定值必须序列化为 作者指定的确切值。其他属性中可能发生的简化,例如删除注释、规范化空格、从其值重新序列化数值标记等,不得发生。

自定义属性 的计算值也必须序列化为 作者指定的确切值,除了替换任何 var() 函数外。

测试
例如,给定以下属性
--y: /* baz */;
--x: /* foo */ var(--y) /* bar */;

--x 的指定值的序列化必须是 "/* foo */ var(--y) /* bar */",而 --x 的计算值的序列化必须是 "/* foo */ /* baz */ /* bar */"

(请注意,值开头的空格会自动被 CSS 解析器修剪;此处未保留。)

之所以有此要求,是因为作者有时会将非 CSS 信息存储在自定义属性中,而“规范化”此信息可能会以破坏作者代码的方式改变它。

例如,将 UUID 存储在自定义属性中,如 --uuid: 12345678-12e3-8d9b-a456-426614174000,需要 UUID 在被脚本访问时按原样回显。

此值在技术上被 CSS 解析为一系列相邻的数字和维度。特别是,段 "-12e3" 被解析为一个数字,等于 -12000。按照 CSSOM 在其他上下文中要求的那样以该形式重新序列化它,将彻底破坏作者对该值的使用。

5. 变更

5.1. 自 2021 年 11 月 11 日 CR 草案以来的变更

5.2. 自 2015 年 12 月 3 日 CR 以来的变更

5.3. 自 2014 年 5 月 6 日末次呼吁工作草案以来的变更

6. 致谢

衷心感谢 CSS 工作组的几位成员多年来保持变量梦想的延续,特别是 Daniel Glazman 和 David Hyatt。感谢邮件列表上的多位人士帮助促成了这一变量实现的开发,特别是 Brian Kardell、David Baron、François Remy、Roland Steiner 和 Shane Stephens。

7. 隐私考量

本规范定义了一种纯粹作者级别的机制,用于在他们控制的页面内传递样式信息。因此,没有新的隐私注意事项。

8. 安全考量

§ 3.3 安全处理过长的变量 提到了一个可以针对“宏扩展”类机制(例如 var() 函数)进行的长期存在的拒绝服务攻击,并强制要求对此类攻击进行防御。

一致性

文档约定

一致性要求通过描述性断言和 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 邮件列表。

候选推荐标准 (CR) 退出标准

为了使本规范能够推进到提案推荐标准 (PR),必须至少有两个独立的、可互操作的每个功能的实现。每个功能可以由不同组的产品实现,不要求所有功能都由单个产品实现。为了实现此标准,我们定义以下术语

independent
每个实现必须由不同的方开发,并且不能共享、重用或派生自另一个合格实现所使用的代码。对本规范实现无影响的代码段不受此要求限制。
可互操作
通过官方 CSS 测试套件中的相应测试用例,或者如果实现不是 Web 浏览器,则通过等效测试。如果此类用户代理 (UA) 用于声明互操作性,则测试套件中的每个相关测试都应创建等效测试。此外,如果此类 UA 用于声明互操作性,则必须有一个或多个额外的 UA,它们也可以以相同的方式通过这些等效测试,以实现互操作性的目的。等效测试必须公开,以供同行评审。
实现
用户代理,即
  1. 实现了该规范。
  2. 对公众可用。该实现可以是出货产品或其他公开可用的版本(即测试版、预览发布版或“每日构建版”)。非出货产品发布版必须已实现该功能至少一个月,以证明其稳定性。
  3. 不是实验性的(即,专门为通过测试套件设计且不打算用于正常使用的版本)。

该规范将保持候选推荐标准状态至少六个月。

索引

本规范定义的术语

通过引用定义的术语

引用

规范性引用

[CSS-ANIMATIONS-1]
Dean Jackson; et al. CSS 动画 Level 1. 2018 年 10 月 11 日. WD. URL: https://w3org.cn/TR/css-animations-1/
[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-3]
David Baron; Elika Etemad; Chris Lilley. CSS Conditional Rules Module Level 3. 2022年1月13日. CR. URL: https://w3org.cn/TR/css-conditional-3/
[CSS-PROPERTIES-VALUES-API-1]
Tab Atkins Jr.; et al. CSS Properties and Values API Level 1. 2020年10月13日. WD. URL: https://w3org.cn/TR/css-properties-values-api-1/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2021年12月24日. CR. URL: https://w3org.cn/TR/css-syntax-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块 Level 3. 2019 年 6 月 6 日. CR. URL: https://w3org.cn/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块 Level 4. 2021 年 12 月 16 日. WD. URL: https://w3org.cn/TR/css-values-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011年6月7日. REC. URL: https://w3org.cn/TR/CSS21/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021年8月26日. WD. URL: https://w3org.cn/TR/cssom-1/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC 中用于指示要求级别的关键词. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器 Level 4. 2018 年 11 月 21 日. WD. URL: https://w3org.cn/TR/selectors-4/
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web 动画. 2021年5月18日. WD. URL: https://w3org.cn/TR/web-animations-1/

参考资料

[CHARMOD-NORM]
Addison Phillips 等人. 万维网字符模型:字符串匹配. 2021 年 8 月 11 日. NOTE. URL: https://w3org.cn/TR/charmod-norm/
[CSS-BACKGROUNDS-3]
Bert Bos; Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 2021年7月26日. CR. URL: https://w3org.cn/TR/css-backgrounds-3/
[CSS-BOX-4]
Elika Etemad. CSS 盒模型模块 Level 4. 2020年4月21日. WD. URL: https://w3org.cn/TR/css-box-4/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承 Level 6. 2021 年 12 月 21 日. WD. URL: https://w3org.cn/TR/css-cascade-6/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS 颜色模块 Level 4. 2021 年 12 月 15 日. WD. URL: https://w3org.cn/TR/css-color-4/
[CSS-EXTENSIONS]
Tab Atkins Jr.. CSS Extensions. 编辑草案. URL: https://drafts.csswg.org/css-extensions/
[CSS-FONTS-4]
John Daggett; Myles Maxfield; Chris Lilley. CSS 字体模块第 4 级. 2021 年 12 月 21 日. WD. URL: https://w3org.cn/TR/css-fonts-4/

属性索引

名称初始值应用于继承百分比动画类型 (Animation type)规范顺序计算值
--* <declaration-value>?保证无效值 (the guaranteed-invalid value)所有元素和所有伪元素(包括具有限制属性列表的元素)不可用离散 (discrete)按语法已代入变量的指定值,或保证无效值