CSS 层叠变量模块一级的自定义属性

W3C 候选推荐快照,

更多关于此文档的详细信息
此版本:
https://www.w3.org/TR/2022/CR-css-variables-1-20220616/
最新发布版本:
https://www.w3.org/TR/css-variables-1/
编辑草案:
https://drafts.csswg.org/css-variables/
以前的版本:
历史记录:
https://www.w3.org/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. (谷歌)
建议为此规范编辑:
GitHub 编辑器

摘要

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

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

本文档的状态

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

本文档由 CSS工作组 作为候选推荐快照发布,使用 推荐轨道。 发布为候选推荐并不意味着获得 W3C 及其成员的认可。 候选推荐快照已接受 广泛审查, 旨在收集实施经验,并得到工作组成员关于 免版税许可的承诺。 本文档旨在成为W3C推荐标准; 它将在2022年8月16日之前保持为候选推荐,以收集更多反馈。

请通过在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值与单位 [CSS-VALUES-3]。 与其他CSS模块的组合可能会扩展这些值类型的定义。

除了其定义中列出的特定属性值之外, 本规范中定义的所有属性 还接受CSS通用关键字作为其属性值。 为了可读性,它们没有被明确重复列出。

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

本规范定义了一组开放的属性,称为自定义属性, 其中,除了其他功能外,还用于定义替换值,供 var() 函数使用。

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

用户代理预期在所有媒体上支持此属性,包括非可视化媒体。

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

测试
自定义属性定义了变量, 使用 var() 表示法引用, 可以用于多种用途。 例如,一个在设计中一致使用少量颜色的页面 可以将这些颜色存储在自定义属性中, 并使用变量来引用它们:
:root {
  --main-color: #06c;
  --accent-color: #006;
}
/* 剩余的CSS文件 */
#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>我从根元素继承了蓝色!</p>
<div>我直接设置了绿色!</div>
<div id='alert'>
  我直接设置了红色!
  <p>我也是红色的, 因为继承了!</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; 也就是说,从第一个逗号到函数结束的内容都被视为回退值。

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

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

/* 在组件的样式中: */ 
.component .header { 
  color: var(--header-color, blue); 
} 
.component .text {
  color: var(--text-color, black); 
} 

/* 在大型应用程序的样式中: */ 
.component { 
  --text-color: #080; 
  /* header-color 没有设置, 
     因此仍然是蓝色, 
     即回退值 */ 
} 

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

测试

要在属性值中替换 var()

  1. 如果 自定义属性的名称是由 var() 函数的第一个参数指定的, 且该 var() 函数用于不可动画的属性中, 则在此算法的剩余部分中,将该 自定义属性视为具有初始值。
  2. 如果由 自定义属性 指定的第一个参数的值为 var() 函数中不是初始值, 则用相应 自定义属性 的值替换 var() 函数。
  3. 否则,如果 var() 函数有第二个参数作为回退值, 则用回退值替换 var() 函数。 如果回退中有任何 var() 引用, 也需要替换它们。
  4. 否则,包含 var() 函数的属性在计算值时间无效

    注意: 其他因素也可能导致属性在 计算值时间无效

测试

CSSOM


注意,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. Invalid Variables

自定义属性 的值是 保证无效值 时, 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);
  /* 等 */
} 

在此简短示例中,--prop4 的计算值为lol lol lol lol lol lol lol lol, 包含原始lol的 8 次重复。 每增加一级会使标识符的数量翻倍; 将其扩展到 30 级仅需几分钟的手工操作, --prop30将包含几乎十亿个标识符的实例。

为了避免此类攻击, 用户代理必须对 var() 函数展开的令牌流长度施加用户代理定义的限制。 如果 var() 展开到的令牌流超过此限制, 它会导致正在展开的属性在 计算值时间无效

测试

本规范未定义应施加的大小限制。 然而,考虑到自定义属性可能含有一千字节或更多文本的合法用例, 建议将限制设得相对较高。

注意:由于资源限制,用户代理可以违反标准的原则在此处依然适用; 用户代理可能分别对自定义属性的支持长度或标识符的支持长度有其他限制。 本节特别指出这种攻击, 因为其历史悠久, 并且在第一次检查时, 其组成部分似乎都不算太大。

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"与规范性文本区分开,像这样:

这是一个说明性示例。

说明性注释以“注释”开头,并通过class="note"与规范性文本区分开,像这样:

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

建议性内容是规范性部分,风格上引起特别关注,并通过<strong class="advisement">与其他规范性文本区分开,像这样: 用户代理(UA)必须提供可访问的替代方案。

测试

与本规范内容相关的测试可以记录在像这样的“测试”块中。 任何此类块均为非规范性。


一致性类别

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

样式表
CSS样式表
渲染器
解释样式表语义并渲染使用样式表的文档的UA
作者工具
编写样式表的UA

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

渲染器符合本规范的条件是,除了根据相关规范解释样式表之外,它还支持本规范定义的所有功能,正确解析并相应地渲染文档。然而,由于设备的限制,UA无法正确渲染文档,并不会导致UA不符合规范。(例如,UA不需要在单色显示器上渲染颜色。)

作者工具符合本规范的条件是,编写的样式表在语法上根据通用CSS语法和本模块中每个功能的单独语法是正确的,并且符合本模块描述的样式表的一致性要求。

部分实现

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

不稳定和专有功能的实现

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

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现是可能的,实施者应发布任何符合规范且能够证明其已根据规范正确实现的CR级别功能的无前缀实现。

为了建立和保持CSS在各个实现中的互操作性,CSS工作组请求非实验性CSS渲染器在发布任何CSS功能的无前缀实现之前,向W3C提交实现报告(如果必要,还包括为该实现报告使用的测试用例)。提交给W3C的测试用例将由CSS工作组进行审查和修正。

有关提交测试用例和实现报告的进一步信息,可以在CSS工作组的网站上找到,网址为http://www.w3.org/Style/CSS/Test/。如有问题,请发送至public-css-testsuite@w3.org邮件列表。

CR退出标准

为了将本规范推进到提议推荐阶段,必须至少有两种独立且可互操作的实现支持每个功能。每个功能可以由不同的产品实现,没有要求所有功能必须由单一产品实现。根据该标准,定义以下术语:

独立
每个实现必须由不同的方开发,且不能共享、重用或派生自其他符合条件的实现所使用的代码。不影响本规范实现的代码部分可免除此要求。
可互操作
通过官方CSS测试套件中的相关测试用例,或者,如果实现不是网页浏览器,则通过等效测试。如果要使用这样的用户代理(UA)来主张互操作性,则每个相关测试都应创建一个等效测试。此外,如果要使用这样的UA来主张互操作性,则必须有一个或多个其他UA能够以相同方式通过这些等效测试,以达到互操作性的目的。这些等效测试必须公开提供以供同行评审。
实现
一个用户代理,符合以下条件:
  1. 实现了规范。
  2. 对公众可用。实现可以是正式发布的产品,也可以是其他公开可用的版本(例如,测试版、预发布版或“每夜构建”)。非正式发布的产品版本必须至少实现该功能一个月,以证明其稳定性。
  3. 不是实验性的(即专门为通过测试套件而设计的版本,且不打算继续用于正常使用)。

本规范将在候选推荐阶段停留至少六个月。

索引

本规范定义的术语

参考中定义的术语

参考文献

规范性参考文献

[CSS-ANIMATIONS-1]
Dean Jackson; et al. CSS Animations Level 1. 2018年10月11日。工作草案。URL: https://www.w3.org/TR/css-animations-1/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5。2022年1月13日。候选推荐标准。URL: https://www.w3.org/TR/css-cascade-5/
[CSS-CONDITIONAL-3]
David Baron; Elika Etemad; Chris Lilley. CSS Conditional Rules Module Level 3。2022年1月13日。候选推荐标准。URL: https://www.w3.org/TR/css-conditional-3/
[CSS-PROPERTIES-VALUES-API-1]
Tab Atkins Jr.; et al. CSS Properties and Values API Level 1。2020年10月13日。工作草案。URL: https://www.w3.org/TR/css-properties-values-api-1/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3。2021年12月24日。候选推荐标准。URL: https://www.w3.org/TR/css-syntax-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3。2019年6月6日。候选推荐标准。URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4。2021年12月16日。工作草案。URL: https://www.w3.org/TR/css-values-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification。2011年6月7日。推荐标准。URL: https://www.w3.org/TR/CSS21/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM)。2021年8月26日。工作草案。URL: https://www.w3.org/TR/cssom-1/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard。现行标准。URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels。1997年3月。最佳现行做法。URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4。2018年11月21日。工作草案。URL: https://www.w3.org/TR/selectors-4/
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web Animations。2021年5月18日。工作草案。URL: https://www.w3.org/TR/web-animations-1/

参考性文献

[CHARMOD-NORM]
Addison Phillips; et al. Character Model for the World Wide Web: String Matching。2021年8月11日。说明性文档。URL: https://www.w3.org/TR/charmod-norm/
[CSS-BACKGROUNDS-3]
Bert Bos; Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3。2021年7月26日。候选推荐标准。URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4。2020年4月21日。工作草案。URL: https://www.w3.org/TR/css-box-4/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 6。2021年12月21日。工作草案。URL: https://www.w3.org/TR/css-cascade-6/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS Color Module Level 4。2021年12月15日。工作草案。URL: https://www.w3.org/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 Fonts Module Level 4。2021年12月21日。工作草案。URL: https://www.w3.org/TR/css-fonts-4/

属性索引

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