CSS数值与单位模块 5级

W3C工作草案

关于本文档的更多信息
本版本:
https://www.w3.org/TR/2024/WD-css-values-5-20241111/
最新发布版本:
https://www.w3.org/TR/css-values-5/
编辑草案:
https://drafts.csswg.org/css-values-5/
历史记录:
https://www.w3.org/standards/history/css-values-5/
反馈:
CSSWG问题仓库
规范内反馈
编辑:
Tab AtkinsGoogle
Elika J. Etemad / fantasaiApple
Miriam E. Suzanne受邀专家
建议为本规范提出编辑意见:
GitHub 编辑器
测试套件:
https://wpt.fyi/results/css/css-variables/

摘要

本CSS模块描述了CSS属性可接受的通用数值与单位,以及在CSS属性定义中用于描述它们的语法。

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

本文档状态

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

本文档由CSS工作组推荐流程工作草案形式发布。 作为工作草案的发布并不意味着已获得W3C及其成员的认可。

本文档为草稿文档,可能随时被更新、替换或废弃为其他文档。不应将此文档作为最终文献引用,仅适合作为进行中的工作参考。

请通过在 GitHub 提交 issue(推荐方式)来反馈意见,反馈时请在标题中包含规范代码“css-values”,示例:“[css-values] ……评论摘要……”。所有 issue 与评论将被归档。 或者,也可以将反馈发送至(归档地址)公共邮件列表 www-style@w3.org

本文件受 2023年11月3日W3C流程文档 管辖。

本文件由依据 W3C专利政策 运作的小组制定。 W3C 维护一份 与小组成果相关的专利披露公开列表; 该页面还包括专利披露说明。 如果个人已知某项专利并认为该专利包含必要权利要求,则必须按照W3C专利政策第6节披露该信息。

本规范仍处于早期探索阶段,欢迎反馈,且预计会有重大变动。

1. 引言

这是针对 CSS数值与单位4级 的差异规范(diff spec)。

1.1. 模块交互

本模块扩展了 [CSS-VALUES-4],该模块替换并扩展了 [CSS21] 的以下部分的数据类型定义:1.4.2.14.3,以及A.2

2. 文本数据类型

参见 CSS值4级 § 4 文本数据类型

3. 值定义语法

参见 CSS值4级 § 2 值定义语法

另外,

  1. 条件记号的布尔组合。 使用 <boolean-expr[]> 记号书写, 表示以递归布尔逻辑运算(使用关键字和括号)组成的表达式, 作用于方括号中指定的语法, 例如 <boolean-expr[ ( &lt;media-feature&gt; ) ]> 来表达 媒体查询

3.1. 函数式记号定义

参见 CSS值4级 § 2.6 函数式记号定义

3.1.1. 函数参数中的逗号

函数式记号通常用逗号分隔其内部语法各部分。 然而,某些函数(如 mix()) 允许值本身包含逗号。 这些值(目前有 <whole-value><declaration-value><any-value>) 被称为可包含逗号的产生式

为便于对这类语法作无歧义处理, 可包含逗号的产生式可以选用花括号 { } 包裹。 这些花括号仅为语法外壳,不属于实际值本身。 具体说明如下:

例如,random-item() 函数的语法为:
random-item( <random-caching-options>, [<declaration-value>?]# )

其中 # 表示逗号分隔的重复项, 所以随机选择三个关键字时,写法类似于:

font-family: random-item(--x, serif, sans-serif, monospace);

有时待选值本身需要包含逗号。此时,用 {} 包裹值,就可以将其内的逗号与函数参数分隔逗号区分开:

font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace});

这样就会在三组字体家族列表中随机选择一个: Times, serifArial, sans-serifCourier, monospace

这不是全有全无;需要时你可以只对部分参数使用 {},其他部分可不加。你也可以在不严格要求的情况下,出于保险考虑对某一值使用花括号。例如:

font-family: random-item(--x, {Times, serif}, sans-serif, {monospace});

此例表示可随机选择三个字体家族列表:Times, serifsans-serifmonospace

然而,这种 {} 包裹只允许用于部分函数参数(那些被定义成可包含逗号的产生式)。若对其他参数使用 {} 包裹则无效,会导致匹配语法失败、产生无效值。例如下例就是无效写法:

background-image: linear-gradient(to left, {red}, magenta);

注意: 由于 {} 包裹在不需要时也允许使用,因此在作者不确定某值是否会包含逗号时,可防御性地加上花括号。比如因 任意替换函数 (如 var() )的影响,font-family: random-item(--x, {var(--list1)}, monospace) 无论 --list1 自定义属性内是否有逗号,这种写法都能正确工作。

函数式记号在可行时应避免带 {} 包裹输出。

下列通用产生式属于可包含逗号的产生式

为兼容历史, <declaration-value> 作为 var() 的回退值定义时属于非严格可包含逗号的产生式。 即:如果不是以“{”开头,可以允许包含逗号和 {} 块,忽略对内容的常规限制。 但如以“{”开头,仍按可包含逗号的产生式的标准规则处理:回退值就是 {} 内容本身,不包括包裹的 {}。

其他上下文可以定义为采用非严格可包含逗号的产生式,但除非必要不推荐这样做。

3.2. 布尔表达式乘子 <boolean-expr[]>

多个上下文 (如 @media@supportsif() 等) 都指定了条件表达式,并允许用布尔逻辑(与/或/非和分组)组合条件。 这些内容都采用了相同的递归语法结构, 所以特别定义了 <boolean-expr[]> 产生式,用于通用表示此类模式。

<boolean-expr[]> 记号对其内部以方括号声明的值类型进行包装, 例如 <boolean[ <test> ]>,意义是既可表示该类型单独存在,也可通过内嵌布尔逻辑(使用 notandor 关键字与小括号分组)组合,形式等价于:

<boolean-expr[ <test> ]> = not <boolean-expr-group> | <boolean-expr-group>
                                            [ [ and <boolean-expr-group> ]*
                                            | [ or <boolean-expr-group> ]* ]

<boolean-expr-group> = <test> | ( <boolean-expr[ <test> ]> ) | <general-enclosed>

<boolean-expr[]> 产生式表示真值、假值或未知值。其值采用三值Kleene逻辑计算, 对于顶层未知(未直接嵌套于另一个 <boolean-expr[]> 内的)将被视为 false,除非有特殊说明; 详见附录B:布尔逻辑

例如,@container 规则允许多种测试,包括尺寸查询、样式查询和滚动状态查询,所有这些都可用布尔逻辑任意组合。 结合 <boolean-expr[]>@container 查询的语法可以这样写:
<container-query> = <boolean-expr[ <cq-test> ]>
<cq-test> = (<size-query>) | style( <style-query> ) | scroll-state( <scroll-state-query> )
<size-query> = <boolean-expr[ ( <size-feature> ) ]> | <size-feature>
<style-query> = <boolean-expr[ ( <style-feature> ) ]> | <style-feature>
<scroll-state-query> = <boolean-expr[ ( <scroll-state-feature> ) ]> | <scroll-state-feature>

逻辑分支的 <general-enclosed> 允许未来兼容性——除非特殊说明,老版本UA遇到新表达式会当作“未知”处理,不会使语法失效。 为与此规则一致,<boolean-expr[]> 语法中的 <test> 项应定义为能够匹配 <general-enclosed>

3.3. 在CSS中指定CSS语法:<syntax> 类型

CSS中某些特性(如 attr() 函数 或已注册自定义属性),允许你声明另一个值的具体解析方式。 这通过 <syntax> 产生式声明, 其格式类似于规范中用于定义CSS特性的 值定义语法,用于表示 语法定义

<syntax> = '*' | <syntax-component> [ <syntax-combinator> <syntax-component> ]* | <syntax-string>
<syntax-component> = <syntax-single-component> <syntax-multiplier>?
                   | '<' transform-list '>'
<syntax-single-component> = '<' <syntax-type-name> '>' | <ident>
<syntax-type-name> = angle | color | custom-ident | image | integer
                   | length | length-percentage | number
                   | percentage | resolution | string | time
                   | url | transform-function
<syntax-combinator> = '|'
<syntax-multiplier> = [ '#' | '+' ]

<syntax-string> = <string>

<syntax-component> 包括 以 <> 包裹(尖括号)的 <syntax-type-name>,对应 受支持语法组件名称之一;或者为 <ident>,代表任意关键字。 同时,<syntax-component> 可带有 乘子,表示值的 列表

注意: 这意味着 <length>length 是两种不同类型:前者描述为 <length>,而后者为关键字 length

多个 <syntax-component> 可以通过 | <delim-token> 组合,以指定顺序依次匹配相应值。

<percentage> | <number> | auto

对此语法,作为<syntax> 解析时,会接受 <percentage><number> 以及关键字 auto

red | <color>

上述 语法定义,用于解析时,会将 red 识别为 标识符,而输入 blue 则识别为 <color>

* <delim-token> 代表 通用语法定义

<transform-list> 语法表示方便写法,等价于 <transform-function>+注意,<transform-list> 后不能跟 <syntax-multiplier>

空白字符不允许出现在 <delim-token>< >)与其包含的 <syntax-type-name> 之间,也不得出现在 <syntax-multiplier> 之前。

注意:这些空白字符限制也适用于 <transform-list>

<syntax-string><string> ,其值可作为 <syntax> 成功解析,并与该 <syntax> 表示的值等价。

注意:<syntax-string> 主要为历史遗留——在定义 <syntax> 前,@property 规则就用 <string> 表示。

3.3.1. 作为 <syntax> 进行解析

<syntax> 的用途通常是指定如何解析另一个值 (比如已注册自定义属性值 或 attr() 的属性值)。 但通用的 按CSS语法解析内容 算法 返回的是未指定的内部结构,因为解析结果可能有歧义,需要后续处理。

为避免上述问题并获得明确结果,应当使用 用 <syntax> 解析

<syntax> 解析,给定 字符串列表组件值 values, 一个 <syntax>syntax, 和可选的元素 el 上下文, 按以下步骤执行。返回CSS值,或 保证无效值
  1. 解析组件值列表values, 记 raw parse 为结果。

  2. 如传入 el,则对 raw parse 应用任意替换函数替换,并设为结果。

  3. CSS语法规则,用 syntax 解析 values, 对遇到 * 语法的情况视为 <declaration-value>?, 记 parsed result 为结果。 如 syntax 用了 | 组合,则取第一个匹配分支的解析结果。

  4. parsed result 为失败,则返回 保证无效值

  5. 断言:此时 parsed result 已为一个或多个CSS值的明确定义列表, 因为每个 <syntax> 分支都定义了解析结果是无歧义的(或 * 语法自身已无歧义)。

  6. 返回 parsed result

注意:该算法不会将解析值进一步转为 计算值;通常具体使用场景会自行计算,如未则需调用方单独处理。

4. 对四级值类型的扩展

参见 CSS数值与单位4级

4.1. 资源定位符:<url> 类型

参见 CSS值4级 § 4.5 资源定位符:<url> 类型

4.1.1. 请求URL修饰符

<request-url-modifier> 是影响 <url> 资源 请求<url-modifier>, 会按照相关的 URL请求修饰步骤 进行处理。 参见 CSS值4级 § 4.5.4 URL处理模型

本规范定义了以下 <request-url-modifier>

<request-url-modifier> = <crossorigin-modifier> | <integrity-modifier> | <referrerpolicy-modifier>
<crossorigin-modifier> = crossorigin(anonymous | use-credentials)
<integrity-modifier> = integrity(<string>)
<referrerpolicy-modifier> = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url)
<crossorigin-modifier> = crossorigin(anonymous | use-credentials)
该修饰符的URL请求修饰步骤如下,给定 request req
  1. requestmode 设置为 "cors"。

  2. 如果指定值为 use-credentials, 则将 requestcredentials mode 设置为 "include"。

<integrity-modifier> = integrity(<string>)
该修饰符的URL请求修饰步骤为,将 request reqintegrity metadata 设置为指定的 <string>
<referrerpolicy-modifier> = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url)
该修饰符的URL请求修饰步骤为,将 request reqreferrer policy 设置为与指定值匹配的 ReferrerPolicy
根据URL值应用请求修饰符,给定 request req<url> url, 需要依次调用 urlURL请求修饰步骤,传入 req

4.2. 二维定位:<position> 类型

<position> 的值表示 对齐目标(如背景图片)在 对齐容器(如其背景定位区)内作为一对边缘偏移(默认左、上)的定位。 其语法为:

<position> = <position-one> | <position-two> | <position-four>
<position-one> = [
  left | center | right | top | bottom |
  x-start | x-end | y-start | y-end |
  block-start | block-end | inline-start | inline-end |
  <length-percentage>
]
<position-two> = [
  [ left | center | right | x-start | x-end ] &&
  [ top | center | bottom | y-start | y-end ]
|
  [ left | center | right | x-start | x-end | <length-percentage> ]
  [ top | center | bottom | y-start | y-end | <length-percentage> ]
|
  [ block-start | center | block-end ] &&
  [ inline-start | center | inline-end ]
|
  [ start | center | end ]{2}
]
<position-four> = [
  [ [ left | right | x-start | x-end ] <length-percentage> ] &&
  [ [ top | bottom | y-start | y-end ] <length-percentage> ]
|
  [ [ block-start | block-end ] <length-percentage> ] &&
  [ [ inline-start | inline-end ] <length-percentage> ]
|
  [ [ start | end ] <length-percentage> ]{2}
]

如果只指定一个值(<position-one>), 则第二个值默认为 center

如果给定两个值(<position-two>), 第一个为<length-percentage>时,代表水平偏移,为 对齐目标对齐容器 左边缘间距离; 第二个 <length-percentage> 代表垂直方向偏移,为它们顶边间距离。

如果两个关键字都是 startend, 第一个表示块轴, 第二个表示内联轴

注意: 一对轴相关关键字可改变顺序,但关键字与长度/百分比不能交换顺序。 如 center leftinline-start block-end 合法, 但 50% left 不合法。startend 非特定轴关键字,因此 start endend start 是不同位置。

如果有四个值(<position-four>), 则每个 <length-percentage> 都代表前面关键字指定边缘之间的偏移。 例如,background-position: bottom 10px right 20px 表示相对于底边向上10px,右边向左20px。

正值表示从对齐容器边缘向的偏移。 负值表示从对齐容器边缘向偏移。

下列声明效果为自左上角起(水平,垂直)偏移:
background-position: left 10px top 15px;   /* 10px, 15px */
background-position: left      top     ;   /*  0px,  0px */
background-position:      10px     15px;   /* 10px, 15px */
background-position: left          15px;   /*  0px, 15px */
background-position:      10px top     ;   /* 10px,  0px */
<position> 也可以相对于其他角定位。 例如,下面的代码使背景图片距离底部10px,右侧3em:
background-position: right 3em bottom 10px

计算值<position> 计算值是两个偏移量(水平和垂直), 都以已计算的 <length-percentage> 表示,为 对齐目标对齐容器左、上边缘之间的距离。

<length-percentage>
<length-percentage> 值指定 对齐目标对齐容器指定边之间的偏移大小。

例如:background-position: 2cm 1cm 表示背景图片左上角距离其背景定位区左上角右侧2cm,下方1cm。

用于水平偏移的 <percentage>,相对于 (对齐容器宽度 - 对齐目标宽度)。 垂直方向的 <percentage> 相对于 (对齐容器高度 - 对齐目标高度)。

例如,取值 0% 0% 时, 对齐目标左上角与 对齐容器左上角重合;100% 100% 则将 对齐目标右下角放在 对齐容器右下角; 75% 50% 时, 对齐目标中心点(75%宽50%高)对齐到 对齐容器的相同点。
元素内图像位置示意图
background-position: 75% 50% 的含义示意图。
top
right
bottom
left
分别表示 对齐目标对齐容器 的上/左/右/下边缘偏移,默认偏移为 0% ,以对应轴为准。
y-start
y-end
x-start
x-end
结果与相应物理边的关键字一致, 具体为所处 [=y轴|y/x 轴上 start / end 方位对应。
block-start
block-end
inline-start
inline-end
结果与相应物理边的关键字一致, 具体为所处 / 内联轴上的 start / end 方位对应。
center
在对应轴上计算为 50% 偏移。

除非另有说明,流向相关关键字根据元素所在的书写模式解析。

注意: background-position 属性也接受三值语法。 该语法被泛用禁止,因为与属性值中其他长度或百分比组件结合时,易产生解析歧义。

需要定义当 background-position 的所有(或部分)分量用 var() 时,如何扩展为 longhand 属性。更多详见 [第9690号问题]

4.2.1. <position> 的解析

当与其他关键字、<length><percentage> 一同出现在语法中时,<position>贪婪地解析:尽可能多地消费分量。

例如 transform-origin 定义了三维位置,语法为 <position> <length>?。 像 left 50px 会被解析为两值 <position>,z分量省略; 而 top 50px 先被解析为單独一个值的 <position>,后接一个 <length>

4.2.2. <position> 的序列化

指定值<position> 时的序列化:

仅指定一个分量时:
  • 自动补全 center 关键字,序列化为两分量值。

指定两个分量时:
  • 关键字以关键字形式序列化。

  • <length-percentage> 序列化为 <length-percentage>

  • 分量依顺序,先水平后垂直序列化。

指定四个分量时:
  • 关键字和偏移值均序列化。

  • 分量依顺序:先水平再垂直;或先块轴内联轴

注意: <position> 的值不会只序列化为单一分量, 即使单值效果等同也是如此,目的是避免某些语法下解析歧义,如 <position> 紧邻 <length> 的场合(如 transform-origin)。

计算值<position> 以两个 <length-percentage> 偏移(依序为左和上边缘)序列化。

4.2.3. <position> 的组合

插值 <position> 定义为每个分量(x, y)独立进行插值, 且均标准化为以左上角为原点的 <length-percentage> 偏移。

加法 <position> 也是每个分量(x, y)各自独立加法, 并标准化为以左上角为基点的 <length-percentage> 偏移。

5. 插值进度函数式记号

本节为探索性草案,尚未被 CSSWG 批准。[第6245号问题]

progress()media-progress()container-progress() 函数式记号用于表示某一值(进度值) 从一个值(进度起始值)到另一个值(进度结束值)的比例距离。 它们分别允许对 数学函数媒体特性容器特性 求进度比例, 使用共同的语法模式:

progress-function() = progress-function( progress value from start value to end value )

每个函数通过<number>,通过计算进度函数来获得结果。

计算进度函数, 传入 进度值进度起始值以及 进度结束值
如果 进度起始值进度结束值 不同

(进度值 - 进度起始值) / (进度结束值 - 进度起始值)

如果 进度起始值进度结束值 相同

如果 进度值等于、少于或大于该值,则分别返回 0、-∞ 或 +∞。

注意: 返回值是普通的<number>, 默认不会与参数类型进行类型一致化

计算所得数值可继续用于其他运算,比如 数学函数混合记号等。

5.1. 计算进度值:progress() 记号

progress() 函数式记号 返回一个 <number> 值, 表示一个 计算进度值) 在另外两个 计算进度起始值进度结束值)之间所处的位置。 progress() 属于数学函数

progress() 的语法如下:

<progress()> = progress(<calc-sum>, <calc-sum>, <calc-sum>)

三个 <calc-sum> 参数分别代表 进度值进度起始值进度结束值

参数计算可得出任何 <number><dimension><percentage>, 但三者类型须一致,否则整个函数无效。

progress() 的值为 <number>,其结果为计算进度函数的输出,并经过与参数类型一致化

是否需要 percent-progress() 记号,还是已有场景会自动转换无需此函数?

注意:progress() 本质上是 calc() 特定表达式的语法糖,因此属于数学函数

5.2. 媒体查询进度值:media-progress() 记号

progress() 类似, media-progress() 函数式记号 返回一个 <number> 值, 代表当前指定媒体查询[MEDIAQUERIES-4] 的取值(作为进度值), 介于该媒体查询的两个明确区间(作为进度起始值进度结束值)。

media-progress() 的语法如下:

<media-progress()> = media-progress(<mf-name>, <calc-sum>, <calc-sum>)

其中,媒体特性对应的 <mf-name>进度值, 两个 <calc-sum> 表示进度起始值进度结束值

指定的媒体特性必须为有效的“范围型”特性, 所给 进度起始值进度结束值 必须为该媒体查询的有效值, 并且二者 计算 类型一致,否则函数无效。

进度起始值进度结束值计算,按媒体特性的规定解释,而非由本函数使用场景决定。

media-progress() 的值为 <number>,通过计算进度函数得到。

注意: media-progress() 不是 数学函数; 它只是一个求解为<number>的普通函数。

5.3. 容器查询进度值:container-progress() 记号

container-progress() 函数式记号 与 media-progress() 语法完全一致, 只是接收 容器特性 [CSS-CONTAIN-3] 替代 媒体特性

container-progress() 的语法如下:

<container-progress()> = container-progress(<mf-name> [ of <container-name> ]?, <calc-sum>, <calc-sum>)

其中 <mf-name> 代表 尺寸特性,可选 <container-name> 用于指定容器分组,在选取要对比的容器时生效。 尺寸特性的当前值为进度值, 两个 <calc-sum> 分别为 进度起始值进度结束值

指定的<mf-name> 必须为有效的尺寸特性, 指定的 进度起始值进度结束值 必须为该 尺寸特性 的有效值, 并且两组 计算 类型一致,否则函数无效。 container-progress() 只能用在属性值上下文中,不能用在如媒体查询中等位置。

进度起始值进度结束值计算,按尺寸特性的定义解释,而非调用上下文。如找不到合适的容器,container-progress() 会基于<size-feature> 查询 小型视口尺寸 得出进度。

media-progress() 的值为 <number>,通过计算进度函数得到。

注意:container-progress() 不是 数学函数; 它只是一个返回 <number> 的普通函数。

6. 混合与插值表达法:*-mix() 系列

该特性 在处理多个断点时表现不佳, 并且 可能需要重新设计[Issue #6245]

CSS 中的若干 mix 表达式 允许表示两个值之间的插值, 即 混合起始值混合结束值, 在它们之间某一给定进度处的值(混合进度值)。 这些 函数式表示法 遵循如下语法模式:

mix-function() = mix-function( <progress>, [=mix start value|start-value=], [=mix end value|end-value=] )

CSS 中的 mix 表达式 包括:

最后还有通用的 mix() 表达式, 它可以表示任何属性值的插值 (但只能表示整个属性值,而不能表示单个组件)。

注: cross-fade() 表达式 还有一种替代语法, 允许混合多于两个的值, 但不允许像 <progress> 那样更复杂的表达式。

mix() 表达式还有一个 变体接受一组关键帧。 它通过引用一个 @keyframes 规则, 并将相应的属性声明取出。 希望允许其他 mix 表达式也接受关键帧, 但如何为一个 组件值(而不是完整的属性值)表示一组关键帧呢?

6.1. 表示插值进度:<progress> 类型

<progress> 值类型表示 在 mix 表达式 中的 混合进度值, 并最终解析为一个百分比。 它可以从媒体查询和动画时间线等来源获取该百分比值, 在用于插值之前也可以通过 缓动函数 进行转换。

其语法定义如下:

<progress> = [ <percentage> | <number> | <'animation-timeline'> ] && [ by <easing-function> ]?

其中:

<percentage-token>
计算为等效的 <number>0% 变为 0100% 变为 1,等等。

注: 这仅允许字面上的百分比, 如 15%; 像 calc(100% / 7) 这样的计算式将不能工作, 因为它们会尝试使用将百分比解析为另一类型的常规规则 (例如在 <length>(在 width 中))。 应使用像 calc(1 / 7) 这样的表达式。

<number>
表示 混合进度值

注: 这允许使用 progress()media-progress()container-progress() 表示法。

<'animation-timeline'>
表示将指定 动画时间线 的进度作为混合进度值。 但值 noneauto 无效。 [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2]
<easing-function>
使用指定的 混合进度值 作为输入,并通过指定的 缓动函数 将其转换为输出的混合进度值。 [CSS-EASING-1]

注: 小于 0 和大于 1 的进度值是有效的; 它们允许表示超出起始值和结束值范围的插值。

注: 虽然 <progress> 本身 可以是一个 <percentage>, 并直接映射为等效的 <number>, 一些解析为 <number> 的函数, 如 progress(), 会使用上下文的一般规则来解析 <percentage>; 例如,在 width 中, 它们会相对于一个长度来解析。

使用 computed value 语义时,若 <progress> 值使用 <percentage><number> 指定, 则其计算值为通过(若有)<easing-function> 转换后的 <number>。 若 <progress> 值以 <'animation-timeline'> 指定, 则其计算值为该 <'animation-timeline'> 和(若有)<easing-function> 的计算值。

6.2. 插值的数值与尺寸值:calc-mix() 表达式

calc-mix() mix 表达式 表示一个插值的数值或尺寸值。 像 calc() 一样,它是一个 数学函数, 具有如下语法形式:

<calc-mix()> = calc-mix( <progress>, <calc-sum>, <calc-sum> )

这两个 <calc-sum> 参数可以解析为任意 <number><dimension><percentage>, 但必须具有 一致的类型,否则该函数无效。 结果的类型将是该 一致类型,并根据 使类型一致的规则<progress> 值的类型进行协调。

一个有效的 calc-mix()used value 是将这两个值按给定的 <progress> 进行插值的结果。 如果 <progress> 值可以计算为一个 <number>, 那么 computed value 同样是将两个 computed values 插值到该 <progress> 值的结果 (换句话说,A * (1-progress) + B * progress) 否则它就是 calc-mix() 表达式本身, 其参数各自根据它们的类型被计算。

6.3. 插值的颜色值:color-mix() 表达式

本规范将 color-mix() 函数式表示法 扩展为一种 mix 表达式,接受以下语法:

<color-mix()> =
  color-mix( [ <progress> && <color-interpolation-method>? ] , <color>, <color> ) |
  color-mix( <color-interpolation-method>, [<color> && <percentage [0,100]>?]#{2} )

第一个 mix 表达式 变体的 used value 等同于将 <progress> 值作为 <percentage>,赋给第二个变体中第二个 <color> 参数的百分比。也就是说, color-mix(progress, color1, color2) 等价于 color-mix(color1, color2 progress) 规范性的第二种变体定义见 CSS Color 5 § 3 混合颜色:color-mix() 函数

<progress> 允许 返回 0–100% 之外的百分比, 但 color-mix() 不允许此类值, 因此需要定义该如何处理此情况。

6.4. 插值的图像值:cross-fade() 表达式

本规范将 cross-fade()函数式表示法 扩展为一种 mix 表达式,接受以下语法:

<cross-fade()> =
  cross-fade( <progress>, [ <image> | <color> ], [ <image> | <color> ] ) |
  cross-fade( <cf-image># )

第一个 mix 表达式 变体的 used value 等同于将 <progress> 值 作为第二个变体中第二个 <color> 参数的百分比。也就是说, cross-fade(progress, image1, image2) 等价于 cross-fade(image1, image2 progress) 规范性的第二种变体定义见 CSS Images 4 § 2.6 合成图像:cross-fade() 表达式

6.5. 插值的变换值:transform-mix() 表达式

transform-mix() mix 表达式 表示一个插值的 <transform-list>, 其语法如下:

<transform-mix()> = transform-mix( <progress>, <transform-list>, <transform-list> )

一个有效的 used valuetransform-mix() 是将这两个值按 <progress> 给定的进度进行插值的结果。 如果 <progress> 值可以计算为一个 <percentage>, 并且这些 <transform-list> 可以在不依赖 used-value-time 信息的情况下被插值, 则 computed value 也将是将两个 computed values 按该 <progress> 值插值的结果; 否则,它就是 transform-mix() 表达式本身, 其参数各自按它们的类型被计算。

transform-mix() 本身是一个 <transform-function>

6.6. 插值的属性值:mix() 表达式

任何两项属性值的插值 可以用 mix() mix 表达式 表示, 它支持两种替代语法模式:

<mix()> =
  mix( <progress> , <whole-value> , <whole-value> ) |
  mix( <progress> && of <keyframes-name> )

第一种语法替代,与其他 mix 表达式 类似, 在其第一项 <whole-value>(即其 混合起始值)与第二项 <whole-value>(即其 混合结束值)之间插值。 第二种则使用 混合进度值 从一组关键帧中插值相应的属性声明, 允许更复杂的插值曲线。

对于标准的 mix 表达式 变体, 如果被 mix() 插值的两个 <whole-value> 在使用该属性时是可插值的, 且插值得到的值可以不使用 mix() 表示, 则 mix()computed value 是将这两个值按 <progress> 给定的进度插值的结果。 否则, mix()computed valuemix()函数式表示法 本身, 其 <progress> 值被计算, 并且其 <whole-value>(如果提供)按该属性的值进行计算。

例如,大多数对 mix() 的使用将在计算值阶段解析:
color: mix(90%, red, blue);
/* 通过简单插值,
   计算为: */
color: rgb(10% 0 90%);

color: mix(90%, currentcolor, black);
/* 无法在计算值阶段完全解析,
   但仍有明确的表示: */
color: color-mix(currentcolor 90%, black 10%);

float: mix(90%, left, right);
/* 离散可动画 */
float: right;

但有少数情况没有中间表示:

transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));
/* 因为函数不匹配,它将通过 matrix() 插值。*/
/* 但 translate(%) 需要布局信息才能转换为 matrix(),*/
/* 因此插值后的值实际上无法被表示。*/
/* 计算为: */
transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));
transform: mix(90% of ripple);

mix() 表达式 是一个 <whole-value>。 另外, 如果其任一 <whole-value> 参数是 不可动画的, 则该表示法无效。

例如,以下声明是无效的, 并将被忽略:
/* 无效的起始值 */
color: mix(90%, #invalid, #F00);

/* 函数与其他值混合 */
background: url(ocean) mix(10%, blue, yellow);

/* 'animation-*' 不可动画 */
animation-delay: mix(0%, 0s, 2s);

7. 杂项值替换函数

7.1. 表示完整属性值:<whole-value> 类型

本规范中定义的若干函数 只能作为属性的“完整值”使用。 例如,background-position: toggle(50px 50px, center); 是合法的, 但 background-position: toggle(50px, center) 50px; 则不合法。 <whole-value> 产生式用于表示这些值。

所有属性隐式地都接受 <whole-value> 作为它们的整个值, 就像它们接受 CSS 全局关键字作为整个值一样。

当作为函数的组件值使用时,<whole-value> 也可以表示 在其使用的属性中通常作为完整值的任意 CSS 值 (包括附加的 <whole-value> 函数)。 不过,有些函数可能会限制 <whole-value> 参数可包含的内容。

7.2. 选择第一个支持的值:first-valid() 表达式

CSS 通过向前兼容的解析方式支持渐进增强: 作者可以在样式规则中多次声明同一个属性, 每次用不同的值, CSS 用户代理会自动使用它能理解的最后一个值, 其余的会被忽略。 这一原则,加上 @supports 规则, 让作者能够编写在新旧用户代理下同时良好工作的样式表。

但如果用 var()(或类似的解析在解析完成后才发生的替换函数), 就会破坏上述机制; CSS 用户代理在解析阶段必须假定属性值是合法的。

first-valid() 函数式表示法 内联了 声明解析内在的回退行为。 与大多数表示法不同, 它的参数可以接受任何合法或非法的语法, 并将其参数中第一个被用户代理支持(被当做合法解析)的值 作为属性的整体值来表示。

<first-valid()> = first-valid( <declaration-value># )

如果所有参数都不构成属性的合法值, 则此属性在 计算值阶段无效

first-valid()<whole-value>

这个名字要不要换掉? 增加进规范时其实还没彻底定。

注: 虽然实际上接收<whole-value>作为参数,first-valid() 实际上被定义为接收<declaration-value>参数, 因为按定义它是为了用在“参数值本身对声明来说有可能是非法”的场景。 <declaration-value> 不会像 <whole-value> 那样强加上下文合法性限制。

7.3. 条件值选择:if() 表达式

if() 表达式是一种任意替换函数,用于表示条件值。 它参数由一个有序、分号分隔的语句列表组成, 每条语句包含一个条件 跟着一个冒号 以及一个值。 一个 if() 表达式代表 参数列表中第一个条件成立时对应的值; 如果没有条件匹配, 那么 if() 表达式代表一个空的 token 流。

if() 表达式 的语法定义如下:

<if()> = if( [ <if-condition> : <declaration-value>? ; ]*
             <if-condition> : <declaration-value>? ;? )
<if-condition> = <boolean-expr[ <if-test> ]> | else
<if-test> =
  supports( [ <supports-condition> | <ident> : <declaration-value> ] ) |
  media( <media-query> ) |
  style( <style-query> )

else 关键词代表 总为真的条件。

解析 if() 函数, 返回第一个成立的 <declaration-value>; 如果都不为 true, 则返回空(即空 token 流)。

注: 与使用 @media/@supports/@container 规则不同, 它们条件为假时仅忽略内部内容并交由层叠顺序决定其它值生效与否。 包含 if() 的声明若条件不满足不会回退到层叠; 任何回退值都必须内联给出。

7.4. 在多个值间切换:toggle() 表达式

toggle() 表达式允许后代元素 在一个值列表中循环选取,而不是继承同一个值。

下面这个例子让 <em> 元素一般显示为斜体, 但如果在嵌套在斜体元素内部则变为正常体:
em { font-style: toggle(italic, normal); }
下例让嵌套列表的项目符号轮番变换, 顶层为 disc, 内层第一次为 circle,再下一级是 square,然后是 box, 然后继续重复从 disc 开始的新一轮。
ul { list-style-type: toggle(disc, circle, square, box); }

toggle() 表达式的语法为:

<toggle()> = toggle( <whole-value># )

toggle() 表达式属于 <whole-value>。 但它不允许嵌套使用, 也不能包含 attr()calc() 表达式; 包含上述内容的声明是无效的。

下列各 toggle() 范例均为无效用法:
background-position: 10px toggle(50px, 100px);
/* toggle() 必须作为该属性的唯一值*/

list-style-type: toggle(disc, 50px);
/* 50px 不是 'list-style-type' 的有效值 */

确定 toggle() 计算值时, 首先分别以该属性唯一值的方式解析每一个参数 得到它们各自代表的计算值, 记为 Cn(第 n 个参数)。 然后,将属性的继承值 与各 Cn 逐个比较。 若最早匹配上 继承值 的为第 n 个, 则 toggle() 的计算值为 Cn+1。 如果命中的正好是最后那个参数, 或没有命中, 那么 toggle() 的计算值就是第一个参数的解析值。

注: 这意味着 toggle() 中值重复会导致提前截断。 比如 toggle(1em, 2em, 1em, 4em) 等效于 toggle(1em, 2em)

注: toggle() 明确比较父元素的计算值, 所以即使是非继承属性也能工作。 这与 inherit 关键字类似, 即使是在非继承属性上也起效。

注: 属性 计算值 是抽象的值集, 而不是某种序列化字符串 [CSS21], 因此计算值之间的比较总是明确一致、符合预期的。 比如, Level 2 的 background-position 计算值 只是两个偏移,各自用绝对长度或百分比表示, 因此 background-position: top centerbackground-position: 50% 0% 所得计算值完全一样。 若属性定义的“计算值”描述模糊或过于严格, 请反馈意见,以便修订。

如果对toggle()用于简写属性时, 会把每个长属性都设为参数展开后与该长属性对应的一组 toggle() 值, 相当于原 toggle() 每个参数单独作为简写属性取值时长属性应得到的参数。

例如下面的简写声明:
margin: toggle(1px 2px, 4px, 1px 5px 4px);

等价于如下展开的长属性声明:

margin-top:    toggle(1px, 4px, 1px);
margin-right:  toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 4px, 4px);
margin-left:   toggle(2px, 4px, 5px);

注意,由于 1px 在 top、4px 在 bottom 出现两次, 它们循环时实际上只有两个值, 而 left/right 仍按三值轮转。 也就是说,以上声明与下述长属性写法效果一致:

margin-top:    toggle(1px, 4px);
margin-right:  toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 4px);
margin-left:   toggle(2px, 4px, 5px);

这可能与预期不符。

7.5. 自定义属性引用:var() 表达式

var() 表达式用于替换 自定义属性值, 详见CSS 可级联变量模块[CSS-VARIABLES]

7.6. 继承值引用:inherit() 表达式

inherit 关键字类似,inherit() 函数式表示法 会解析为父级属性的 计算值。 不过它不是取同名属性值, 而是取第一个参数指定属性的分词 计算值。 第二个参数(如果有)则作为回退, 当第一个参数解析为 保证无效值时使用。

inherit() 是 一种任意替换函数,其语法如下:

<inherit()> = inherit( <custom-property-name>, <declaration-value>? )

解析 inherit() 函数, 返回第一个参数指定的自定义属性的继承值, 若有第二参数则用作回退。

注: 未来 CSS 层级可能允许 inherit() 直接引用标准 CSS 属性; 但因 计算值 的分词化方式目前并未对所有属性完全标准化, 此功能暂缓至 Level 5 之后。 注意 计算值used value 不同, 且不一定等于 getComputedStyle() 得到的 resolved 值; 所以即便能写 inherit(width), 也经常只会返回关键字 auto, 而不是实际像素数值 <length>

7.7. 属性引用:attr() 表达式

attr() 函数 用选定元素的 属性值替换到属性声明里, 类似 var() 用自定义属性做插值。

attr() = attr( <attr-name> <syntax>? , <declaration-value>?)

<attr-name> = [ <ident-token> '|' ]? <ident-token>

attr() 的参数为:

<attr-name>

指定所引用属性的名称, 类似 <wq-name>(见 [SELECTORS-3]) 但不可用通配前缀。

如未指定命名空间 (即如 attr(foo) 这样只给名字), 则默认为 null 命名空间。 (通常用不到命名空间,尤其在 HTML 和 SVG 里。) 与 属性选择器一样, <attr-name> 是否区分大小写由文档语言决定。

如果 attr() 用于某元素的属性, 则引用该元素同名属性; 若用于伪元素, 属性查找将视为对其关联元素

<syntax>

指定如何 按 CSS 语法解析属性值为 CSS 值。 若解析失败则触发回退。

省略 <syntax> 参数时, 属性的字面文本将作为 CSS 字符串值使用, 无任何 CSS 解析 (包括 CSS 转义、去空格、去注释等)。

注: 这和用 * 作为语法不同, 后者依然触发 CSS 解析 (但只要能解析就行,无额外约束), 直接用解析结果替换, 而不是包装成 <string> 值。

<declaration-value>

attr() 指定一个回退值, 当该属性缺失或其值无法按指定类型解析时,将使用此回退值代替属性值。

如果省略了 <syntax> 参数, 则当回退被省略时默认为空字符串; 否则如果省略了回退,则默认使用 保证无效值

若属性中含有一个或多个 attr() 函数, 且这些函数语法上无误, 则整个属性在解析阶段一律视作语法合法。 只有在计算值阶段、attr() 替换后再做语法检查。

注意默认值不需要与期望类型一致。 例如,如果作者指定属性类型为 <number px>, 默认值也可为 auto, 如 width: attr(size <number px>, auto);
此例展示 attr() 用法可在 XML 文件中作可视化数据展示:
<stock>
  <wood length="12"/>
  <wood length="5"/>
  <metal length="19"/>
  <wood length="4"/>
</stock>

stock::before {
  display: block;
  content: "To scale, the lengths of materials in stock are:";
}
stock > * {
  display: block;
  width: attr(length <number em>, 0px);
  height: 1em;
  border: solid thin;
  margin: 0.5em;
}
wood {
  background: orange url(wood.png);
}
metal {
  background: silver url(metal.png);
}

7.7.1. 属性值替换:attr() 表达式

attr() 属于一种任意替换函数, 类似 var(), 所以在计算值阶段会被(如有可能)替换为它所代表的值; 否则,将被替换为保证无效值, 这会导致其声明在计算值阶段无效

解析 attr() 函数,请按如下步骤:
  1. el 为应用包含该 attr() 函数样式的元素。 令 attr name 为函数中指定的属性名。 令 syntax 为函数中指定的 <syntax>, 若省略则为 null。 令 fallback 为函数中指定的 <declaration-value>? 参数, 若省略则为保证无效值

  2. 如果 el 不存在名为 attr name 的属性, 则返回保证无效值fallback。 否则,令 attr value 为该属性值。

  3. 如果 syntax 为 null, 返回 CSS <string>,其值为 attr value

    注: 此时对值不会做任何解析或修改。

  4. 按 <syntax> 解析 attr value,并传入 syntaxel。 返回结果和 fallback

7.7.2. 安全性

attr() 函数 可以引用页面原本并不打算用于样式的属性, 这些属性有可能包含敏感信息 (例如页面脚本用的安全令牌)。

一般而言,这种用法问题不大。 在大多数情形下,想用 attr() 把信息从页面提取出来 并传给恶意方是很难的。 唯一的例外是 URL。 如果能纯用 CSS 把任意属性值构造为 URL, 一旦允许第三方 CSS, 就很容易把属性里的信息发送给恶意方。

为防范此类情况, attr() 产出的值会被视为 attr()-污染, 包含 attr()-污染值的函数同样被视为污染。已注册自定义属性所含 attr(),对应的 attr()-污染 值在 var() 替换过程中会被保留污染标志。

attr()-污染值直接或间接用于 <url> ,会导致该声明计算值阶段无效

例如,以下写法都无效:

但用于其它场景则没问题, 即便用法靠近 url:

注: 实现此限制时, 需要对来自 attr() 的值全程追踪 dirty 标志, 因为此类值可经 注册自定义属性 完全变成纯字符串, 不能仅靠检查表达式来判定。 注意非字符串类型也会受到影响, 比如利用 string() 这种可把其它类型转为字符串的函数也能触发, 如 --foo: attr(foo number); background-image: src(string(var(--foo))) 同样应为无效。

8. 生成随机值

在设计中加入一定“随机性”常常非常实用, 比如避免页面上重复出现的元素千篇一律、死板呆滞, 或简单地为页面增添些许灵动但不产生干扰。

random()random-item() 函数 (随机函数) 允许作者在页面中引入随机性, 同时又让这种随机在设计上保持可预测性, 作者可以决定随机值是跨多个位置复用还是每次实例唯一。

随机数生成的具体方式由 UA 决定。 应当两个不同的随机值之间没有明显相关性, 但本规范并不规定这种“无相关性”在密码学上的强度到底如何。 作者严禁随机函数用于任何依赖高强度加密的场景。

8.1. 生成随机数值:random() 函数

random() 是一种 数学函数,它代表取自最小值与最大值之间、 服从均匀分布的一个随机值, 可选地指定间隔(step),令选值局限于区间等步长节点:

<random()> = random( <random-caching-options>? , <calc-sum>, <calc-sum>, [by <calc-sum>]? )

<random-caching-options> = <dashed-ident> || per-element

其参数如下:

<random-caching-options>

可选的 <random-caching-options> 用于控制某 random() 是否和页面中其它 random() 得到相同或不同随机值。 详见§ 8.3 生成/缓存随机值:<random-caching-options>取值

默认情况下,random() 会解析为单个值, 使用该样式的所有元素都共用一个值, 两个参数完全一样的 random() 会返回相同随机值。

单独给 <dashed-ident> 并无实际作用, 但可让形参不同, 令多个原本参数一致的 random() 区分产生不同值。

per-element 关键字会让 random() 在每个应用该函数的元素上 各自生成独立随机值,而不是样式表中统一解析出一个。

<calc-sum>, <calc-sum>

这两个必需的计算值参数用于指定函数可能返回的最小和最大值。 两端都包含在内(即结果可能等于 min 或 max)。

若最大值小于最小值, 则会视为最大值等于最小值。

例如 random(100px, 300px) 将返回介于 100px300px 的一个随机 <length> 值: 可能为 100px300px,或介于两者之间如 234.5px 等。
by <calc-sum>

可选项,指定步进: 函数可能解析出的值局限为 min + (N * step) 形式, 其中 N 是从所有在区间范围内解的非负整数里等概率选择的一个。

例如 random(100px, 300px, by 50px) 可能为 100px150px200px250px300px; 不会出 120px

最小值总可能出现, 但最大值不一定, 如果最大值不是从最小值起步进整数倍。 例如 random(100px, 300px, by 30px) 最大奖励 280px(距最小值步进 6 次)。

注意舍入问题可能有影响: random(100px, 200px, by 100px / 3) 一定会是三种值 (100px、大约 133.33px166.67px), 但 200px 能否出现则要看舍入精度。 稳妥起见,最大值可以略高于期望终点,比如 random(100px, 201px, by 100px / 3)

round() 的定义, CSS 并无“天然精度”, 但 step 参数可指定精度。

比如 random(100px, 500px, by 1px) 只会取整 px 值; random(1, 10, by 1) 只会取整数,等等。

注: 步进的定义不允许 先在范围内生成一随机值再对其舍入, 因为这会导致每个值出现概率不均。 例如 random(100px, 200px, by 50px) 必须三个可能(1/3)等概率; 用舍入法会让 150px 出现频率变双倍。

所有计算参数可为任意 <number><dimension><percentage>, 但必须同类型,否则函数无效; 返回结果类型和参数相同。

例如 random(50px, 100%, by 1em) 是合法的 (前提是百分比在上下文可合法转为 <length>), 因为三参数都能解释为长度值。

random(50px, 180deg) 是非法的, 因长度和角度不是同一类型。

random() 可在其参数计算值化为数字后就被简化

注: 这意味着random() 通常计算值阶段解析, 因此会以静态数值继承。 但如果参数计算 要到用值阶段才能解析 (如包含必须到布局时才能计算的<percentage>), 那么继承的就是 random() 本身。 (这和 <percentage> 本身的行为一致, 百分比会继承为百分比, 因此子元素可能解析为其他数值。)

理论上在非属性上下文也应该允许用 random(), 只要没用 per-element; 比如 @media (max-width: random(100px, 500px)) {...} 语法和含义都是合理的。 但我们是不是还是不允许好?

8.1.1. 参数取值范围

random(A, B, by C) 中, 如果 A 或 B 是无穷大, 则结果为 NaN。 如果 C 是无穷大, 则结果为 A。

(如果 C 为零或负数, 结果是 A, 但这属于常规定义范围内的行为。)

注: 和其他 数学函数 一样, 若任何参数计算结果是 NaN, 最终结果也为 NaN。

8.2. 从列表中随机选取一项:random-item() 函数

random-item() 函数 会从参数列表中 随机选出一个项作为结果。

<random-item()> = random-item( <random-caching-options> , [ <declaration-value>? ]# )

必需<random-caching-options> 参数语义与 random() 完全一致。 (详细见 § 8.3 生成/缓存随机值:<random-caching-options> 取值。)

random() 类似, 其中 <dashed-ident> 可用来让类似的 random-item() 产生不同的随机值, per-element 能让每个元素解析为不同的随机值。

除此之外, random-item() 实例分组判等的唯一标准就是参数数量。

random-item(--x, red, blue, green)random-item(--x, 1, 2, 3) 总会解析为索引相同的参数项: 不是 red1,就是 blue2,或 green3。 这样各属性就能实现随机组间协同。

random-item(--x, red, blue, green)random-item(--x, 1, 2, 3, 4) 则完全独立,12 种组合都有可能。

注: <random-caching-options> 参数在 random-item() 中必填, 但在 random() 为选填, 既是为了解析需求 (无法区分 random-item(--foo, --bar, --baz) 是三个 <declaration-value> 还是两个加一个 <random-caching-options>), 也避免随机项因为参数数量区分容易关联到同一实例。

剩下的参数为任意 CSS 值序列。 random-item() 随机均匀选出其中之一作为结果。

random-item() 函数属于 任意替换函数, 类似 var()

所以如果你用了 random-item()

需要定义 任意替换函数, 可能应放在 Variables, 因为类似能力的函数还会有不少。

既然 random-item() 类似 var(), 可能应规定只能用于属性值里。 (这一规范也许也适用于所有此类函数。) 虽然 random() 从本质上不同, 但出于一致性考虑可能也应有限制。

8.3. 随机值生成与缓存:<random-caching-options> 参数

在 JavaScript 等编程语言中, 代码有明确的时间顺序, 所以可以确定 Math.random() 之类是在什么时候执行的。 还可用变量保存结果, 明确表示随机值是多处共用还是各自独立。

而 CSS 是声明式语言 (代码并不按顺序“执行”, 也无法知道“执行”多少遍); 虽很容易让许多元素用同一个样式, 却很难让它们分配不同值 (导致 random() 的属性到底是同值还是异值很不清楚); 而“变量”的能力也极有限 (很难控制某个随机值多次重用)。

为了解决这些问题, random()random-item() 明确规定了如下缓存语义:

“元素或伪元素的唯一标识” 的生命周期应与 JavaScript 对该元素的引用一致 (或与 关联元素+足够信息标识伪元素)。 分属不同文档的元素 (即使是同页多次刷新后的元素)应该获得不同唯一值。 (不是强制要求,以便可伪随机生成, 但应该足够独特,让开发者无法依赖跨文档同值。)

另外,随机生成方法确保不同文档(包括同一页面刷新)下的操作也获得不同值。

例如,下面样式表中:
.random-square {
  width: random(100px, 500px);
  height: random(100px, 500px);
}

两处函数的 随机缓存键 完全一致:(100px, 500px, null, null, null)。 这意味着两个值总完全相等, 故产生的元素必为正方形, 长宽都在 100px ~ 500px 范围内。 此外,所有 .random-square 元素都将有相同尺寸。

如果这样:

.random-rect {
  width: random(100px, 500px);
  height: random(--x, 100px, 500px);
}

两者 随机缓存键 不同: width 的为 (100px, 500px, null, null, null), 而 height(100px, 500px, null, --x, null)

结果两个属性会用不同的随机值, 因而元素一般不会正方形。 但所有 .random-rect 元素依然一致。

修改任一参数也会导致缓存键不同, 如下两个声明长宽值互不关联:

.random-rect-2 {
  width: random(100px, 500px);
  height: random(100px, 500px, by 50px);
}

不过只要最终用值相同, 两个外表不同的函数结果仍可能一致。 例如:

.random-square-2 {
  font-size: 16px;
  width: random(160px, 320px);
  height: random(10em, 20em);
}

这两个函数表面不同, 实际解析后 缓存键 一致, 都是 (160px, 320px, null, null, null), 因而长宽总相等。

默认样式表内每个 random() 实例 实际会统一解析为一个固定值, 应用于所有用到该属性的元素。 用 per-element 关键字可改变此行为。

比如:

.foo { width: random(100px, 500px); }

所有 .foo 元素宽度随机但一致。

而如果:

.foo { width: random(per-element, 100px, 500px); }

每个 .foo 元素都是独一无二的宽度。

但注意该唯一性是针对“元素”,而不一定是“值”唯一。 例如:

.random-squares {
  width: random(per-element, 100px, 500px);
  height: random(per-element, 100px, 500px);
}

每个 .random-squares 元素得到一组全随机值, 但该元素的 widthheight 必然相同, 所以仍然正方形。 因为两属性中 随机缓存键 均为 (100px, 500px, null, null, [元素唯一值]), 两者会解析为元素上的同一数值。

这样自定义属性里的随机值结果更可控。 上述代码等价于:

.foo {
  --size: random(per-element, 100px, 500px);
  width: var(--size);
  height: var(--size);
}

9. 树结构计数函数:sibling-count()sibling-index() 表达式

sibling-count() 函数式表示法<integer> 形式 表示目标元素父节点下所有子元素的总数量。

sibling-index() 函数式表示法<integer> 形式 表示目标元素在其父节点的所有子元素中的序号。 类似 :nth-child()sibling-index() 序号从 1 开始。

注: counter() 函数能实现与 sibling-index() 类似的能力, 但返回值类型为 <string> 而非 <integer>

用于伪元素时, 效果等同于指定在其源元素上。

注: 除了 选择器,CSS 其他部分(包括 sibling-count()sibling-index())都以 平坦树(flat tree) 作为依据。

注: 这两个函数将来可能会扩展,支持加 of <selector> 参数, 类似 :nth-child(),用于筛选部分子元素。

10. 内部尺寸参与计算:calc-size() 函数

当在两个确定尺寸之间过渡, 或对现有的确定尺寸做微调时,calc() 用起来非常顺手: 100% 和 20px 的一半是 calc(50% + 10px),左/右有 15px 间距的 20% 是 calc(20% + 15px * 2), 诸如此类。

但如果你要调整或过渡的目标尺寸是内在尺寸,这些操作就无法实现, 无论是出于实际需要还是兼容性考虑。 calc-size() 函数 允许你用安全和明确的方式对内在尺寸做数学运算。

<calc-size()> = calc-size( <calc-size-basis>, <calc-sum> )

<calc-size-basis> = [ <intrinsic-size-keyword> | <calc-size()> | any | <calc-sum> ]

<intrinsic-size-keyword> 产生式 匹配上下文允许的任意内在尺寸关键字。 例如在 width 属性中, 可匹配 automin-contentstretch 等。

为什么 calc-size() 支持嵌套?

允许 calc-size() 作为 basis 参数, 让作者可以用变量赋值(如 calc-size(var(--foo), size + 20px)), 这样变量只要本来对该属性有效就永远有效

若只用 calc() 就不行 — 例如 ,如果 --foo: calc-size(min-content, size + 20px), 或者 --foo: min-content, 那么 calc( (var(--foo)) + 20px ) 直接失败。

嵌套结构会在插值和用值时被简化, 因此插值及其它效果发生时,basis 最终都会落为简单值; 详见§ 10.1 calc-size() 的简化

第一个参数是calc-size basis, 第二个是calc-size calculation。 对于任一个参数, 如果给的是 <calc-sum>, 它的 类型 必须与 match <length-percentage>, 并且结果必须能解为 <length>

calc-size calculation 内, 若 calc-size basis 不是 any, 则允许使用 size 关键字。 此关键字为 <length>, 在 用值阶段求值。

calc-size() 表示一个内在尺寸。 它明确不是 <length>; 需要接受 calc-size() 的地方,语法须显式包含它。

为何不直接让 calc() 支持内在关键字?

理论上,本可不引入 calc-size(),而让 calc(auto * .5) 合法,从而可直接插值。

这会有不明显的小麻烦,即混用关键字依然不被允许,但表面上却很合理 (如 calc((min-content + max-content)/2) 看起来没问题,实际上是不合法的)。

更大的问题是,无法平滑过渡百分比。 calc(50%) 只有在百分比为确定时, 才是 calc(100%) 的一半; 否则,两者实际上通常同一个大小(要看上下文,也许是 0px 也许还是 auto 计算结果)。

用一个独立函数把基础值和计算表达彻底分开, 就能让所有情况平滑插值。

还有很多效果, 有些很细微,有些很大, 都依赖于元素是否是内在尺寸或确定尺寸。 如果用 calc(), 那“元素是否内在尺寸”在动画中途等情况下会变, 例如 calc(min-content * .2 + 20px * .8)) 是, 但 calc(20px) 就不是, 动画到头时布局会发生突变。

(这类似于 opacity:1opacity: 0 的动画引起 stacking context 变化。 opacity 可用 .999 近似回退, 但 no one 愿意把 auto 动画到 calc(auto * .0001) 只为保证其内在属性不丢。)

再次强调,专用函数如 calc-size(auto, 20px) 能全程保持内在尺寸身份, 所以布局行为整个动画过程都平稳一致,即便实际值变成了确定长度。

10.1. calc-size() 的简化

数学函数类似, 在 指定值计算值 阶段, calc-size calculation (以及 basis 若为 <calc-sum> 时) 都会简化到最大程度, 规则见 CSS Values 4 § 10.10.1 Simplification

若要规范化插值用 calc-size()
基础本身是另一个 calc-size()

外层函数的基础改为内层函数的基础, 内层函数的 calc-size calculation 插入到外层 calculation。

否则,若 基础<calc-sum> 且其 type match <length>(无百分比)

any 替代基础, 初始基础 插入calculation 中。

否则,若 基础 是包含百分比的其它 <calc-sum>

100% 替换 basis,并对初始 basis 去百分化, 再插入到 calculation。

(如有必要,上述规则可递归应用。)

若任何 插入计算 返回失败,则整个操作立即失败。

注: 经规范化后, calc-size()基础 只会是关键字或 100%

为什么百分比简化成这样?

这样百分比简化,能确保过渡是线性的。

比如假定 100% 就是 100px。

若从 `calc-size(100px, size * 2)`(结果为 200px) 过渡到 `calc-size(50%, size - 20px)` (结果为 30px), 若两参数都做插值, 半程时会是 `calc-size(75px, size * 2 * .5 + (size - 20px) * .5)` (解得 102.5px), 这并不是 30 和 200 的一半(应为 115px)。 各参数按顺序插值甚至插值后再算一般会形成二次曲线效果。

相反,若把 basis 参数替换到 calculation, 你会得到 `calc-size(percentage, 100px * 2)` 和 `calc-size(percentage, (size * .5) - 20px)`, 插值得到半程时为 `calc-size(percentage, 100px * 2 * .5 + ((size * .5) - 20px) * .5)`, 这正好是 115px,其它点也是线性的。

若要去百分化 calc-size 计算式: calc
  1. calc 中每个<percentage-token>, 替换为 (size * N),其中 N 为百分数值/100。 返回 calc

注:50% + 20px 简化成 (size * .5) + 20px

若要插入 calc-size 计算式 calc 一个 insertion value:
  1. 如果 calc 没含有 size 关键字,则什么都不做。

  2. 否则,将 calc 中所有 size 替换为 insertion value,加括号。

  3. 如替换后值大于 UA 定义上限,返回失败。

    注: 这一保护措施与变量替换的攻击防护相同; 参见 CSS Variables 1 § 3.3。 不过,长 calc-size() 实用性远低于自定义属性,UA 可设得更低。

10.2. calc-size() 的解析

calc-size() 在所有方面都被视为其 calc-size basis(其中 any 表示未指定的确定尺寸)。

但实际布局时, basis 的值会以 calc-size calculation 得到的新值替代, 其中 size 关键字 代表 basis 的原始尺寸。

(如果 calc-size basisanycalc-size() 是个确定长度, 就等于其 calc-size calculation

比如, 下面元素 height: calc-size(auto, round(up, size, 20px)) 处理得与 height: auto 一样, 但其尺寸会被向上取整到 20px 的整数倍。

calc-size calculation 值时, 若上下文中百分比值不是确定的, 则解析为 0px, 否则正常解析。

(若 basis 里有百分比,处理方式不同;简化会把百分比搬入 calculation 并换成 size, 此时 basis 就变成 100%,等同于该上下文里正常含义,如有可能让属性当成 auto 等等。)

basis 里的百分比总是正常解析, 这样你可以平滑地过渡到任何 size, 不管目标是啥。 比如没 calc-size() 时, 从 100% 过渡到 0px 只有当百分比为确定才平滑, 否则动画过程整段属性都表现为 auto(尺寸根本没动画)。

而 calculation 里的百分比则如不能确定直接为 0, 以免 calc-size() 期间行为前后突变; 某些情况下 min-content100% 会导致布局不同, 所以 calc-size() 必须全程像一个或另一个失败。

10.3. calc-size() 的插值

两个 calc-size() 之间可以插值, 条件是(两者都规范化插值后):

有任意一方 规范化插值 失败

这两个值不能插值。

两者 基础 完全一致

结果 基础 就取该值。

有一方 基础any

结果 基础 用不是 any 的那一方。

结果的calc-size calculation 为两输入 calculation 的插值。

注: 这些插值限制确保 calc-size() 不会出现同一时刻包含不同内在属性的行为。 例如 min-contentmax-content 在某些情况下布局会有重大差异, calc-size() 必须全程像其中之一伪装。 也正因如此,关键字间不能直接动画, 不能如 automin-content 动画。

某些 calc-size() 还可与 <length-percentage><intrinsic-size-keyword> 插值。 判断能否及如何插值时, 可把非 calc-size() 值视作: calc-size(any, value )(若 value 是 <calc-sum>); 或 calc-size(value , size)(否则), 然后按前述规则处理。

比如 calc-size() 允许与 height: auto 互动画:
details {
  transition: height 1s;
}
details::details-content {
  display: block;
}
details[open]::details-content {
  height: auto;
}
details:not([open])::details-content {
  height: calc-size(any, 0px);
}

会自动插值 介于 calc-size(auto, size)calc-size(any, 0px) 之间。 打开 details 半秒后, ::details-content 的 height 就是 calc-size(auto, size * .5), 正好为打开后的 1/2; 动画全程高度平滑变化。

注: calc-size() 设计用以确保 向 calc-size(any, 确定 尺寸) 过渡总是能顺利工作, 不论另一端指定法为何。

注: “升级普通值为 calc-size()” 的机制, 会把 <length-percentage> 值放入 calculation。 这样带百分比的值可和内在尺寸关键字互动画, 但意味着百分比不是确定时会解成零。 想要百分比行为严格等同于具体尺寸, 应显式写成 calc-size(50%, size)

10.4. 尺寸关键字的插值:interpolate-size 属性

注: 如果我们能时光倒流,这个属性大可不必存在。 它之所以存在,是因为很多已有的样式表假设 内在尺寸关键字 (例如 automin-content 等) 不可动画。 所以该属性存在是为了让样式表可以选用 预期的插值行为。 在根元素上指定 interpolate-size: allow-keywords 就会为整页采用新行为。 如果不涉及兼容性问题,我们建议都用这个。

名称: interpolate-size
取值: numeric-only | allow-keywords
初始值: numeric-only
适用于: 所有元素
是否继承:
百分比: 不适用
计算值: 与指定值相同
规范顺序: 按语法
动画类型: 不可动画
numeric-only
<intrinsic-size-keyword> 无法参与插值。
allow-keywords
只要其中一个是 <intrinsic-size-keyword>,另一个是 <length-percentage>,就可以插值。 此时会将 <intrinsic-size-keyword> keyword 视作 calc-size(keyword, size),并按 § 10.3 calc-size 插值中的规则处理。 其他情况则依然不支持 <intrinsic-size-keyword> 插值。

interpolate-size 生效的 是动画可能开始时元素的计算值。 对于 CSS 过渡而言, 即 after-change style 状态下的值。 动画过程中不会因为 interpolate-size 变化而停止或启动。

附录 A:任意替换函数

任意替换函数是一种函数式表示法,在被解析时, 会用其它值替换自身, 而这些值在解析时可能无法预知——因此解析这些函数时需等到计算值阶段。

注: 由于任意替换函数计算值 阶段解析, 如果替换后值无效, 该属性会等效地回退到 unset 行为, 而不是像解析阶段无效时那样回退到早前的层叠值。 见 无效替换

除非另有说明,任意替换函数可以用在任何属性值的任意部分 (包括可嵌套其它函数式表示法 内); 但在其它上下文中无效。

是否应该允许这些函数在属性以外的上下文下使用?

例如如下代码错误尝试用变量做属性名:
.foo {
  --side: margin-top;
  var(--side): 20px;
}

不是margin-top: 20px; 写进样式的等价方式。 此声明名不合法会被直接丢弃。

若属性值包含一个或多个 任意替换函数, 且这些函数本身语法无误, 则整个值的语法在解析阶段都视为合法。

任意替换函数 会在样式 计算过程中 被替换, 这发生在所有值转换或反查之前。 如果属性经过 替换 后不满足语法, 则该声明 在计算值阶段无效

如果属性值 在 替换后, 只剩一个 CSS 全局关键字(以及空白/注释), 那么属性行为就如该关键字一直是其 指定值

例如, 下例语法没问题, 但变量替换后会变为无意义内容:
:root { --looks-valid: 20px; }
p { background-color: var(--looks-valid); }

因为 20pxbackground-color 的无效值, 属性会 计算值阶段无效, 变为 transparentbackground-color 的初始值)。

若该属性默认可继承, 比如 color, 则本例会取继承值而不是初始值。

虽然 var() 函数 不能从自定义属性 值获得CSS 全局关键字——如 --foo: initial; 只会让自定义属性触发显式默认行为—— 但可以在回退参数里用全局关键字:
p { color: var(--does-not-exist, initial); }

--does-not-exist 属性不存在或 计算值阶段无效var() 就会用回退 initial, 使属性表现如原本就是 color: initial。 这让属性取文档初始 color, 而不是像没写回退时那样继承。

每个 任意替换函数都必须定义如何为自己解析, 返回可选的 resultfallback。 只要 result 没包含 保证无效值, 就用 result 替换函数; 否则用 fallback。(fallback 不需额外解析;如果用到,替换操作会完成这一步。)

注: 可参考如 resolve a var() function

若要为 value 执行任意替换函数替换:
  1. 遍历 value 中每个 任意替换函数 func

    1. 解析 func。 得到 resultfallback

      若未返回 result, 取 保证无效值。 若未返回 fallback, 也设为 保证无效值

    2. result 没包含 保证无效值

      result 替换 func

      否则,若 fallback 没包含 保证无效值

      fallback 替换 func

      否则

      把整个 value 替换成保证无效值,然后退出算法。

  2. value 中还有 任意替换函数(比如替换后出现新的),重复上一步。

  3. 正常按语法检查 value。若非法, 改为 保证无效值

注意替换发生在 CSS token 层级 [css-syntax-3], 而非文本拼接。 你不能把一部分变量直接拼进一个 token 里:
.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);
}

这也意味着替换后的值不能直接序列化输出。 比如类似例子:

.foo {
  --gap: 20;
  --not-px-length: var(--gap)px;
}

替换后 --not-px-length 的序列化不是 20px, 否则被重新解析就是合成的单个标量(px 维度); 实际序列化会加注释分割 token, 如 px, 以保证重解析时还是两个。

无效替换

替换导致属性值 含有 保证无效值 时, 该声明即被视为计算值阶段无效。 这时, 该属性的计算值如下:

属性为未注册的自定义属性
属性为注册自定义属性通用语法

计算值即为 保证无效值

否则

计算值等同该属性的继承值或初始值,具体是继承属性还是非继承属性, 等效写成 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 规则。

注: 计算值阶段无效 的概念,是因为任意替换函数 不能像语法错误那样提前失败, UA 发现值无效时, 旧层叠值早已丢失。

简写属性中的替换

任意替换函数会为 简写属性和长属性的解析及序列化带来复杂性。

如果某 简写属性 值含有 任意替换函数, 那么对应的 长属性 必须设置为特殊的、作者不可见的 待替换值, 表示该简写包含 任意替换函数, 因此需等 替换 后才能确定长属性。

该值后续参与层叠, 计算值阶段,在 替换后, 简写需重新解析, 各长属性再获得准确值。

注: 未用任意替换函数的简写,解析时会拆分成 长属性 并各自参与层叠,原简写则被遗弃。 含 var() 时, 因为 var() 的替换结果不确定,不能这样直接拆分。

待替换值如被 API 观察,应序列化为空字符串。


简写属性序列化时 要汇总其各 长属性, 合成能正确解析出原值的串。

如果某简写的所有 长属性 都来自同一 待替换值(仍保留原简写里的 任意替换函数), 则 简写属性 序列化就恢复原文本。

否则,若任一 长属性 仍为 待替换值 或含未被 替换任意替换函数, 简写属性序列化为空字符串。

安全处理过长的替换值

如果实现不够严谨, 某些任意替换函数(例如 var()) 可以用于类似“亿笑攻击(billion laughs attack)”的利用:

.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, 包含了原始 lol 的 8 个副本。 每多加一级都会使标识符数量加倍; 如果扩展到仅仅 30 层, --prop30 里面就会包含近十亿个这个标识符,几分钟手工也能实现。

为防止此类攻击, UA 必须对任意替换函数展开后的 token 流长度加以 UA 自定的限制。 若某 任意替换函数 展开后超出此限制,则直接替换为保证无效值

本规范未规定应施加多大的限制。 但由于确有自定义属性需要存储 1KB 甚至更多内容的情形, 建议限制值设置得足够大。

注: UA 因资源受限可以违反规范的这一原则,这里同样适用; 比如 UA 可以另外规定自定义属性值最大长度,或者标识符最大长度。 本节单独点出这种攻击,是因为它历史悠久, 以及它在初看时每个片段都不会很大却可组合成攻击。

附录 B:布尔逻辑

为便于 CSS 未来扩展,<boolean-expr[]> 产生式 通常将其 <general-enclosed> 分支按未知处理, 并使用三值 Kleene 逻辑解析其布尔结果。 某些情况下(像 @supports),<general-enclosed> 会被定义为 false; 这时逻辑就退化成标准布尔代数。

三值布尔逻辑递归应用于一个布尔条件 test 时如下:

若顶层 <boolean-expr[]> 得到 unknown, 且包容场景没明确规定 unknown 如何处理, 则结果为 false。

注: unknown 不会“溢出”到 3 值逻辑表达式外部,除非有明确定义, 类似 NaN 不会“溢出”到顶层计算那样。

鸣谢

首先,编辑们要感谢所有为本模块前一版本做出贡献的人。

其次,我们还要感谢 Guillaume Lebas、 L. David Baron、 Mike Bremford、 Sebastian Zartner, 以及特别感谢 Scott Kellum,感谢他们对 Level 5 提出的想法、批评和建议;

变更记录

2024 年 9 月 17 日工作草案 以来的变化:

2024 年 9 月 13 日首个公开工作草案 起的变化:

Level 4 以来的新增内容

CSS Values and Units Level 4 起增加:

安全性说明

本规范允许 CSS <url> 值修改请求的多项参数。 虽 CSS 是新加这些能力, 但 imglink 元素和 JavaScript 早就支持了全部这些能力。

attr() 函数允许 HTML 属性值参与 CSS 计算, 可能暴露原本无法通过 CSS 访问的敏感信息。 见§ 7.7.2 安全性

隐私性说明

本规范中定义的单位暴露了用户屏幕尺寸和默认字体大小, 但这些早可被 JS 轻松观测,因此不构成新隐私风险。 类似地,media-progress() 表达式也会 暴露用户环境和偏好, 但这些已可通过 媒体查询 获知。

attr() 函数允许 HTML 属性值参与 CSS, 可能暴露原本无法通过 CSS 访问的敏感信息。 见§ 7.7.2 安全性

合规性

文档约定

合规性要求结合叙述性断言和 RFC 2119 术语表述。本规范中规范部分的关键词 “MUST”、 “MUST NOT”、 “REQUIRED”、 “SHALL”、 “SHALL NOT”、 “SHOULD”、 “SHOULD NOT”、 “RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应按 RFC 2119 的说明进行解释。 为了可读性,本规范未将这些词以大写形式出现。

本规范中的所有内容均为规范性部分,除非明确标记为非规范性、示例或注释。[RFC2119]

本规范的示例以“for example”开头,或用 class="example" 明显区分,例如:

这是一个说明性示例。

说明性注释以“Note”起头,并用 class="note" 区分,如下:

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

提示(advisements)是规范性部分,用以引起特别关注,通过 <strong class="advisement"> 区分,例如: 用户代理(UA)必须提供无障碍替代。

合规类别

对本规范的合规性分为三类:

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

样式表若使用了本规范定义的语法,且语句按通用 CSS 语法和各特性单独语法均有效,则视为符合本规范。

渲染器符合本规范,须能正确解析样式表、支持本规范定义的全部特性,并据此渲染文档。但若因设备限制无法正确渲染文档,不视为不合规。(例如,UA 不要求在黑白显示器上呈现彩色。)

编辑工具合规,须能产生语法正确、符合 CSS 通用语法和本模块每项特性的样式表,并满足本模块描述的其它样式表合规性要求。

部分实现

为便于作者利用向前兼容的解析规则指定回退值,CSS 渲染器必须将其功能尚不支持的任何 at-rule、属性、属性值、关键字及其他语法结构都视为无效(并 视情况忽略)。 特别是,用户代理不得在同一多值属性声明中选择性地忽略不支持的值并使用支持的值:一旦有任一值被认定无效(所有不支持的值都必须如此),CSS 要求整个声明被忽略。

不稳定与专有特性实现

为避免与将来 CSS 标准特性冲突,CSSWG 建议遵循最佳实践来实现不稳定特性和专有扩展

非实验性实现

一旦规范达到候选推荐标准(CR),就允许出现非实验性实现,且实现者应当发布非前缀的实现版本,前提是能证明根据规范正确实现。

为确保 CSS 在不同实现间的互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布未加前缀的功能实现前,向 W3C 提交实现报告(及必要时用于该报告的测试用例)。提交的测试用例将由 CSS 工作组审核和修订。

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

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS Box Alignment Module Level 3. 17 February 2023. WD. URL: https://www.w3.org/TR/css-align-3/
[CSS-ANIMATIONS-1]
David Baron; et al. CSS Animations Level 1. 2 March 2023. WD. URL: https://www.w3.org/TR/css-animations-1/
[CSS-ANIMATIONS-2]
David Baron; Brian Birtles. CSS Animations Level 2. 2 June 2023. WD. URL: https://www.w3.org/TR/css-animations-2/
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 11 March 2024. CR. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 13 January 2022. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-5]
Chris Lilley; et al. CSS Color Module Level 5. 29 February 2024. WD. URL: https://www.w3.org/TR/css-color-5/
[CSS-CONDITIONAL-3]
Chris Lilley; David Baron; Elika Etemad. CSS Conditional Rules Module Level 3. 15 August 2024. CR. URL: https://www.w3.org/TR/css-conditional-3/
[CSS-CONDITIONAL-5]
Chris Lilley; et al. CSS Conditional Rules Module Level 5. 5 November 2024. WD. URL: https://www.w3.org/TR/css-conditional-5/
[CSS-CONTAIN-3]
Tab Atkins Jr.; Florian Rivoal; Miriam Suzanne. CSS Containment Module Level 3. 18 August 2022. WD. URL: https://www.w3.org/TR/css-contain-3/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. 30 March 2023. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-EASING-1]
Brian Birtles; Dean Jackson; Matt Rakow. CSS Easing Functions Level 1. 13 February 2023. CR. URL: https://www.w3.org/TR/css-easing-1/
[CSS-EASING-2]
CSS Easing Functions Level 2. 29 August 2024. WD. URL: https://www.w3.org/TR/css-easing-2/
[CSS-FONTS-4]
Chris Lilley. CSS Fonts Module Level 4. 1 February 2024. WD. URL: https://www.w3.org/TR/css-fonts-4/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS Images Module Level 3. 18 December 2023. CR. URL: https://www.w3.org/TR/css-images-3/
[CSS-IMAGES-4]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS Images Module Level 4. 17 February 2023. WD. URL: https://www.w3.org/TR/css-images-4/
[CSS-PROPERTIES-VALUES-API-1]
Tab Atkins Jr.; Alan Stearns; Greg Whitworth. CSS Properties and Values API Level 1. 26 March 2024. WD. URL: https://www.w3.org/TR/css-properties-values-api-1/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. 17 December 2021. WD. URL: https://www.w3.org/TR/css-sizing-3/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons. CSS Box Sizing Module Level 4. 20 May 2021. WD. URL: https://www.w3.org/TR/css-sizing-4/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 24 December 2021. CR. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS Transforms Module Level 1. 14 February 2019. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSS-TRANSFORMS-2]
Tab Atkins Jr.; et al. CSS Transforms Module Level 2. 9 November 2021. WD. URL: https://www.w3.org/TR/css-transforms-2/
[CSS-TRANSITIONS-1]
David Baron; et al. CSS Transitions. 11 October 2018. WD. URL: https://www.w3.org/TR/css-transitions-1/
[CSS-TYPED-OM-1]
Tab Atkins Jr.; François Remy. CSS Typed OM Level 1. 21 March 2024. WD. URL: https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 12 March 2024. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS Values and Units Module Level 5. 17 September 2024. WD. URL: https://www.w3.org/TR/css-values-5/
[CSS-VARIABLES-1]
Tab Atkins Jr.. CSS Custom Properties for Cascading Variables Module Level 1. 16 June 2022. CR. URL: https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. 30 July 2019. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. REC. URL: https://www.w3.org/TR/CSS21/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[MEDIAQUERIES-4]
Florian Rivoal; Tab Atkins Jr.. Media Queries Level 4. 25 December 2021. CR. URL: https://www.w3.org/TR/mediaqueries-4/
[MEDIAQUERIES-5]
Dean Jackson; et al. Media Queries Level 5. 18 December 2021. WD. URL: https://www.w3.org/TR/mediaqueries-5/
[REFERRER-POLICY]
Jochen Eisinger; Emily Stark. Referrer Policy. 26 January 2017. CR. URL: https://www.w3.org/TR/referrer-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-3]
Tantek Çelik; et al. Selectors Level 3. 6 November 2018. REC. URL: https://www.w3.org/TR/selectors-3/
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. 11 November 2022. WD. URL: https://www.w3.org/TR/selectors-4/
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web Animations. 5 June 2023. WD. URL: https://www.w3.org/TR/web-animations-1/
[WEB-ANIMATIONS-2]
Brian Birtles; Robert Flack. Web Animations Level 2. 21 February 2023. WD. URL: https://www.w3.org/TR/web-animations-2/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

说明性引用

[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. 4 August 2024. WD. URL: https://www.w3.org/TR/css-box-4/
[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS Cascading and Inheritance Level 4. 13 January 2022. CR. URL: https://www.w3.org/TR/css-cascade-4/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 6. 6 September 2024. WD. URL: https://www.w3.org/TR/css-cascade-6/
[CSS-COLOR-4]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS Color Module Level 4. 13 February 2024. CR. URL: https://www.w3.org/TR/css-color-4/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.. CSS Lists and Counters Module Level 3. 17 November 2020. WD. URL: https://www.w3.org/TR/css-lists-3/
[CSS-SCOPING-1]
Tab Atkins Jr.; Elika Etemad. CSS Scoping Module Level 1. 3 April 2014. WD. URL: https://www.w3.org/TR/css-scoping-1/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification. 12 April 2016. WD. URL: https://www.w3.org/TR/CSS22/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 26 August 2021. WD. URL: https://www.w3.org/TR/cssom-1/

属性索引

名称 取值 初始值 适用元素 继承 百分比 动画类型 规范顺序 计算值
interpolate-size numeric-only | allow-keywords numeric-only all elements yes n/a not animatable per grammar as specified

问题索引

这是一个与 CSS Values and Units Level 4 的差异规范。
需要定义当 background-position 的长属性如何拆解此语法,比如某些(或全部)分量用了 var()[Issue #9690]
本节为探索性草案,尚未获得 CSSWG 批准。[Issue #6245]
我们是否需要 percent-progress() 记法,还是足够多场合自动转换已经足够?
该特性 处理多个断点的能力较弱可能还需重设方案[Issue #6245]
mix() 记法也有一套可以接受关键帧的写法。它通过引用 @keyframes 规则并取出对应属性声明实现此功能。希望其它 mix 相关写法也能接受关键帧,但如果想让 component value(而不是完整属性值)组一套关键帧,如何标准化?
<progress> 允许返回超出 0-100% 的百分比,但 color-mix() 不允许,需要规定转化后如何处理。
是否需要叫这个名?添加时没有完全确定。
理论上只要不使用 per-element,在非属性上下文用 random() 应该没问题;比如 @media (max-width: random(100px, 500px)) {...} 等用法语义明晰。不过我们是不是其实仍应禁止?
需要定义 arbitrary substitution function,或许应放在 变量 里,因为未来还有多个函数用到这一机制。
由于 random-item() 与 var() 类似,建议只能在属性内用(其它此类函数也应有同样约束);虽然 random() 与本质不同,也可为统一风格而限制。
是否允许这些函数在属性外其他上下文中使用?