CSS 数值与单位模块 4 级

W3C 工作草案,

关于本文档的更多详情
此版本:
https://www.w3.org/TR/2024/WD-css-values-4-20240312/
最新发布版本:
https://www.w3.org/TR/css-values-4/
编辑草案:
https://drafts.csswg.org/css-values-4/
历史记录:
https://www.w3.org/standards/history/css-values-4/
反馈:
CSSWG 问题库
规范内反馈
编辑:
Tab Atkins (Google)
Elika J. Etemad / fantasai (Apple)
建议编辑此规范:
GitHub 编辑器
测试套件:
https://wpt.fyi/results/css/css-values/

摘要

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

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

本文档状态

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

本文档由 CSS 工作组 作为推荐标准制定流程下的工作草案发布。 作为工作草案发布,并不代表 W3C 及其成员的认可。

本文档为草案,可能随时被更新、替换或废弃。 除非作为开发中工作,否则不应作为正式引用。

请通过在 GitHub 提交 issue(推荐),并在标题中包含规范代码“css-values”,格式如:“[css-values] …评论摘要…”来反馈意见。 所有问题和评论都会被归档。 或者,也可以反馈到(归档)公共邮件列表 www-style@w3.org

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

本文件由遵循 W3C 专利政策 的工作组制定。 W3C 维护了公开披露的专利列表,其中列出了与该组交付物相关的任何专利披露; 该页面还包括披露专利的说明。 任何知晓专利且认为其包含必要声明的个人,必须按照W3C 专利政策第6节披露相关信息。

1. 引言

每个 CSS 属性的值定义字段可以包含关键字、数据类型(出现在 <> 之间),以及它们如何组合的信息。通用的数据类型(<length> 是最常用的)可被许多属性使用,这些类型在本规范中进行了描述,而更具体的数据类型(如 <spacing-limit>)则在各自的模块中定义。

1.1. 模块交互

本模块取代并扩展了 [CSS2] 规范中 1.4.2.14.3A.2 部分的数据类型定义。

2. 值定义语法

此处描述的 值定义语法 用于定义 CSS 属性的有效值集合(以及 CSS 其他部分的有效语法)。被如此描述的值可以包含一个或多个组件。

2.1. 组件值类型

组件值类型有几种指定方式:

  1. 关键字值(例如 autodisc 等),直接以字面量出现,无需引号(如 auto)。

  2. 基本数据类型,出现在 <> 之间(如 <length><percentage> 等)。对于 数值数据类型,该类型记法可以使用下文所述的括号范围记法来标注任意范围限制。

  3. 属性值范围,表示与同名属性相同的值模式。这些写作属性名,并以单引号括起,放在 <> 之间,例如 <'border-width'><'background-attachment'> 等。

    这些类型不包括CSS 全局关键字,如 inherit。此外,如果属性的值语法是逗号分隔重复,则相应类型不包括顶层 逗号分隔列表乘子。(例如,如果有一个名为 pairing 的属性被定义为 [ <custom-ident> <integer>? ]#,则 <'pairing'> 等价于 [ <custom-ident> <integer>? ],而不是 [ <custom-ident> <integer>? ]#。)

    为什么要去除乘子?

    这些值类型去除了顶层乘子,是因为顶层逗号分隔重复主要用于协调型列表属性,而当简写属性合并多个此类属性时,需要未重复的语法,以便可以构造其自己的逗号分隔重复。

    如果没有这种特殊处理,每个这样的长属性都必须为内部值定义一个特设产生式,这会让语法整体更难理解。

  4. 函数记法及其参数。这些写作函数名,后跟一对空括号,放在 <> 之间,例如 <calc()>,并指代同名的 函数记法

  5. 其他非终结符。这些写作非终结符名称,放在 <> 之间,如 <spacing-limit>。注意 <border-width><'border-width'> 的区别:后者表示 border-width 属性的语法,前者则要求在别处进行显式展开。非终结符的定义通常位于规范中首次出现的位置附近。

某些属性值定义还包含斜杠(/)、逗号(,)和/或括号作为字面量,这些表示其对应的标记。其他出现在组件值中的非关键字字面字符(如“+”),必须用单引号括起来。

语法中的逗号在特定情况下是可以省略的,当它用于分隔语法中的可选项时。在属性或其他 CSS 值的顶层列表或函数参数列表中,如果:

例如,如果一个函数可以按顺序接受三个参数,但它们都是可选的,可以这样写语法:
example( first? , second? , third? )

在这种语法下,example(first, second, third) 合法,example(first, second)example(first, third)example(second) 也是合法的。但 example(first, , third) 是非法的,因为有一个逗号不再分隔两个选项;同样,example(,second)example(first,) 也是非法的。example(first second) 也非法,因为逗号仍然必须分隔选项。

如果逗号不是可隐式省略的,语法就必须更复杂才能准确表达参数的可省略方式,从而大大降低特性的简洁性。

所有 CSS 属性也都接受CSS 全局关键字值作为属性值的唯一组成部分。为便于阅读,这些关键字不会在属性值语法定义中显式列出。例如,border-colorCSS Cascading and Inheritance Level 3 下的完整值定义为 <color>{1,4} | inherit | initial | unset(即使语法只写作 <color>{1,4})。

注意: 这意味着通常情况下,将这些关键字与同一声明中的其他组件值组合会导致声明无效。例如,background: url(corner.png) no-repeat, inherit; 是无效的。

2.2. 组件值组合符

组件值可以通过以下方式组合成属性值:

并列的优先级高于双和号,双和号优先于双竖线,双竖线优先于竖线。因此,以下两行是等价的:

  a b   |   c ||   d &&   e f
[ a b ] | [ c || [ d && [ e f ]]]

对于可变顺序的组合符(||、&&),语法顺序无关紧要:同一分组内的组件可以任意顺序出现。因此,以下两行是等价的:

a || b || c
b || a || c

注意: 组合符并不是结合的,因此分组很重要。例如 a || b || ca || [ b || c ] 是不同的语法:前者允许 b a c 这样的值,后者则不允许。

2.3. 组件值乘子

每种类型、关键字或带括号的分组后面都可以跟以下修饰符之一:

+# 乘子可叠加为 +#;同理,#? 也可叠加为 #?。这些叠加等价于后面的乘子作用于前面的乘子结果(用分组也可表达,但语法复杂时会导致括号过多影响可读性)。

对于重复的组件值(*+#),UA 必须支持至少 20 次重复。如果属性值包含超过支持次数的重复,则该声明必须被忽略视为无效。

2.4. 组合符与乘子模式

有一小组常见方式用于按特定数量和顺序组合多个独立的组件值。尤其常见的需求是:从一组组件值中,作者必须选择零个或多个、一个或多个,或全部,并且顺序可以固定或任意。

所有这些都可以通过简单的组合符乘子组合模式表达:

顺序固定 顺序任意
零个或多个 A? B? C? A? || B? || C?
一个或多个 [ A? B? C? ]! A || B || C
全部 A B C A && B && C

注意,所有“顺序任意”的情况都是用组合符表达的,而“顺序固定”都是并列变体。

2.5. 组件值与空白符

除非另有说明,空白符和/或注释可以出现在用上述组合符乘子组合的组件之间、之前和之后。

注意: 在许多情况下,组件之间实际上必须有空格,以区分各自。例如,值 1em2em 会被解析为一个 <dimension-token>,数值为 1,标识符为 em2em,这是无效单位。此时,必须在 2 前添加空格,才能分别解析为 1em2em 两个长度。

2.6. 函数式记法定义

函数式记法的语法定义为以下序列:

  1. 函数名写作标识符,后跟左括号(如 example(),或用 <function-token> 产生式表示任意函数名。

  2. 函数参数(如有),用值定义语法表达。

  3. 一个右括号字面量。

函数参数被视为隐式分组,相当于被方括号([ ... ])包围。

例如,如下语法:
example( <length> , <length> )

会匹配函数名为“example”,参数为“<length> , <length>”的函数。

例如,选择器语法通用地定义伪类,允许冒号后跟任意函数名:
<pseudo-class-selector> = ':' <ident-token> | ':' <function-token> <any-value> ')'

这表示任意函数名,<any-value> 为函数参数。

由于 函数式记法隐式分组其内容,任何组合符的作用范围仅限于函数参数。例如,函数式记法语法定义 example( foo | bar ) 等价于 example( [ foo | bar ] )

2.7. 属性值示例

以下是一些带有相应值定义字段的属性示例:

属性 值定义字段 示例值
orphans <integer> 3
text-align left | right | center | justify center
padding-top <length> | <percentage> 5%
outline-color <color> | invert #fefefe
text-decoration none | underline || overline || line-through || blink overline underline
font-family [ <family-name> | <generic-family> ]# "Gill Sans", Futura, sans-serif
border-width [ <length> | thick | medium | thin ]{1,4} 2px medium 4px
box-shadow [ inset? && <length>{2,4} && <color>? ]# | none 3px 3px rgba(50%, 50%, 50%, 50%), lemonchiffon 0 0 4px inset

2.8. 非终结符定义与语法产生式块

<position><calc()> 这样的非终结符的精确定义,通常在CSS 语法产生式块中给出。这些定义通常以如下格式的预格式化区块表示:

<foo> 语法定义如下:
<foo> = keyword | <bar> |
        some-really-long-pattern-of-stuff
<bar> = <length>

每条定义单独占一行,由要定义的非终结符、一个 =,以及其展开的值定义语法片段组成。定义可以跨多行,直到下一行以新产生式开头或到达产生式块结尾(以先到者为准)为止。

在上述例子中,<foo> 的定义跨两行,第三行为 <bar> 启动新定义。(裸 =值定义语法中永远无效,因此新定义的起始是明确的。)

3. 值的组合:插值、加法与累积

某些过程(例如 过渡动画)会组合两个 CSS 属性值。 下列组合操作——针对两个计算值 VAVB,生成 计算值 Vresult——进行了定义。 对于非交换操作(如矩阵乘法或不匹配变换列表的累积),VA 表示操作的第一个项,VB 表示第二个项。

插值
给定两个属性值 VAVB, 产生距离 p 的中间值 Vresult,其中 p = 0 时为 VAp = 1 时为 VB

p 的取值范围为 (−∞, ∞), 这是因为缓动函数的影响。 因此,该过程还必须定义 p 超出 [0, 1] 区间时的外推行为。

加法
给定两个属性值 VAVB, 返回两者的和 Vresult

注意:虽然加法通常可以用定义插值所用的加权和函数来表达, 但并非总是如此。 例如,变换矩阵的插值涉及分解并插值矩阵分量, 而加法依赖于矩阵乘法。

如果某个值类型未定义加法的具体过程,或被定义为不可加, 其 加法操作仅为 Vresult = VB

累积
给定两个属性值 VAVB, 返回将两个操作数组合的结果 Vresult, 其中 VB 被视为 VA增量
注意:对于很多动画类型,如数字或长度,累积被定义为与加法相同。

常见的不同定义情况出现在基于列表的类型中, 此时加法可能被定义为列表追加, 而累积 可能被定义为分量加法。 例如,滤镜列表值 blur(2)blur(3)加法结果是 blur(2) blur(3)累积结果则为 blur(5)

如果某个值类型未定义累积的具体过程, 其 累积操作与加法相同。

这些操作仅定义在计算值上。 (因此,无需定义如 <length>15pt5em 如何相加,因为此类值会先被解析为规范单位后再传递给上述过程。)

3.1. 范围检查

插值可能导致结果值超出属性的有效范围,即使所有插值输入都是有效的; 这在 p 超出 [0, 1] 区间时尤其常见,但某些缓动函数即使在该区间内也可能导致超出。 如果在插值、加法、累积后最终结果超出目标上下文允许的范围, 并不会导致声明无效。 而是必须将该值裁剪(clamp)到目标上下文允许的范围, 裁剪方式与数学函数完全一致(参见§ 10.12 范围检查)。

注意: 即使插值结果超出范围,加法/累积可能“修正”结果使其回到有效范围。 因此,裁剪仅适用于应用所有插值相关操作后的最终结果。

4. 文本数据类型

文本数据类型 包括各种关键字和标识符,以及字符串(<string>)和 URL(<url>)。 除了预定义关键字的大小写或某些属性专门定义的情况外, 不会进行任何标准化处理,甚至不会进行 Unicode 标准化: 属性的指定值计算值 就是解析后(包括字符集转换和转义)所提供的 Unicode 值。[UNICODE] [CSS-SYNTAX-3]

CSS 标识符, 通常用 <ident> 表示, 由符合 <ident-token> 语法的一系列字符组成。[CSS-SYNTAX-3] 标识符不能加引号; 否则会被当作字符串解析。 CSS 属性接受两类标识符预定义关键字作者自定义标识符

注意: <ident> 产生式不用于属性值定义——应使用 <custom-ident>。它主要用于定义其他语法结构。

所有文本数据类型在插值时均为离散,且不可加

4.1. 预定义关键字

在值定义字段中,具有预定义意义的 关键字以字面量出现。 关键字属于标识符,并且ASCII 不区分大小写(即 [a-z] 和 [A-Z] 等价)。

例如,border-collapse 属性的值定义为:
Value: collapse | separate

使用示例:

table { border-collapse: separate }

4.1.1. CSS 全局关键字:initialinheritunset

如上所述,所有属性都接受CSS 全局关键字, 这些关键字表示所有 CSS 属性通用的值计算方式。 这些关键字在 CSS 层叠与继承模块中有规范性定义。

其他 CSS 规范也可以定义额外的全局关键字。

4.2. 无前缀的作者自定义标识符:<custom-ident> 类型

某些属性接受任意作者自定义标识符作为组件值。 这种通用类型用 <custom-ident> 表示, 代表任何不会被该属性值定义误判为预定义关键字的 CSS 标识符。 此类标识符完全区分大小写 (即使用“完全相同”操作进行比较), 即使在 ASCII 范围内 (如 exampleEXAMPLE 是两个不同且无关的自定义标识符)。

CSS 全局关键字 不是有效的 <custom-ident>default 关键字是保留字,也不是有效的 <custom-ident>。 使用 <custom-ident> 的规范必须明确指定 还有哪些关键字被排除在 <custom-ident> 之外(如有)——例如说明该属性值定义中的所有预定义关键字均被排除。 被排除的关键字在所有 ASCII 大小写组合下都被排除。

在解析属性值中位置不明确的关键字时, <custom-ident> 产生式只有在没有其他未满足产生式可认领该关键字时,才能认领它。

例如,速记声明 animation: ease-in ease-out 等价于长写声明 animation-timing-function: ease-in; animation-name: ease-out;ease-in<easing-function> 产生式认领,属于 animation-timing-function, 留下 ease-out<custom-ident> 产生式认领,属于 animation-name

注意: 在设计带有 <custom-ident> 的语法时, <custom-ident> 应始终“位置明确”, 保证不会与任何属性关键字发生冲突。 也可以通过使用 <dashed-ident> 来避免此类冲突。

4.3. 有前缀的作者自定义标识符:<dashed-ident> 类型

某些场景既接受作者自定义标识符,也接受 CSS 定义的标识符。 如果不加以区分, 会导致 CSS 新增值时出现困难;UA 需要分析现有用法, 并冒险认为作者定义的标识符与新 CSS 值重复的概率足够低, 从而赋予新值特殊 CSS 意义不会破坏现有页面。

虽然 CSS 中有许多遗留情况正是这样混用两类值空间, <dashed-ident> 类型旨在为作者自定义标识符与 CSS 定义标识符的区分提供简便办法。

<dashed-ident> 产生式 是 <custom-ident>, 并具备完全区分大小写的特性, 还要求必须以两个连字符(U+002D HYPHEN-MINUS)开头。

<dashed-ident> 仅用于作者自定义名称。 CSS 永远不会为自身定义 <dashed-ident>

例如,自定义属性 需要和 CSS 定义的属性区分, 因为 CSS 会不断新增属性。 为此,自定义属性名要求为 <dashed-ident>, 示例:
.foo {
  --fg-color: blue;
}
<dashed-ident> 也用于 @color-profile 规则, 用于区分作者自定义色彩配置与预定义配置(如 device-cmyk), 并允许 CSS 将来定义更多预定义(但可覆盖)配置, 无需担心与作者自定义配置冲突:
@color-profile --foo { src: url(https://example.com/foo.icc); }
.foo {
  color: color(--foo 1 0 .5 / .2);
}
随着更多作者可控语法的增加,CSS 在未来会更多使用 <dashed-ident>。 CSS 工具, 如将自定义语法转换为标准 CSS 的预处理器,也使用 <dashed-ident>, 以避免与未来 CSS 设计发生冲突。

例如, 如果某 CSS 预处理器新增了一个“自定义” at 规则, 不应写作 @custom, 因为这会与将来官方的 @custom 规则冲突。 应该用 @--custom, 这样就保证不会与 CSS 已定义内容冲突。

更好的做法是用 @--library1-custom, 这样如果 Library2 也新增自己的 “custom” at 规则 (写作 @--library2-custom), 就不会发生冲突。 理想情况下,该前缀应是可配置的, 这样作者可以手动避免冲突。

4.4. 带引号的字符串:<string> 类型

字符串(String)<string> 表示。 当以字面值书写时, 它们由用双引号或单引号括起来的一系列字符组成, 对应于 <string-token> 产生式, 详见 CSS 语法模块 [CSS-SYNTAX-3]

双引号不能直接出现在双引号包裹的字符串中,除非进行转义(如 "\"""\22")。 单引号的情况类似('\'''\27')。
content: "this is a 'string'.";
content: "this is a \"string\".";
content: 'this is a "string".';
content: 'this is a \'string\'.'

出于美观或其它原因,可以将字符串分为多行书写,但此时换行符本身必须用反斜杠(\)转义。该换行符随后会从字符串中移除。例如,以下两个选择器是完全相同的:

示例:

a[title="a not s\
o very long title"] {/*...*/}
a[title="a not so very long title"] {/*...*/}

由于字符串不能直接包含换行符,如需在字符串中包含换行,请使用转义符 "\A"。 (十六进制A是 Unicode(U+000A)中的换行字符,但在 CSS 中代表通用“换行”概念。)

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

<url> 类型, 通过 url()src() 函数书写, 表示一个 URL, 即资源的指针。

<url> 的语法如下:

<url> = <url()> | <src()>

<url()> = url( <string> <url-modifier>* ) | <url-token>
<src()> = src( <string> <url-modifier>* )
下面示例展示了如何将 URL 作为背景图片使用:
body { background: url("http://www.example.com/pinkish.gif") }

出于兼容性原因,url() 可以在不加引号的情况下书写 URL,此时会被特殊解析<url-token> [CSS-SYNTAX-3]。 因为这种特殊解析,url() 只能直接指定 URL;src() 不具备该解析规则, 因此其 URL 可以通过函数提供, 如 var()

例如,以下声明是等价的:
background: url("http://www.example.com/pinkish.gif");
background: url(http://www.example.com/pinkish.gif);

下面这两种写法也有同样效果:

background: src("http://www.example.com/pinkish.gif");
--foo: "http://www.example.com/pinkish.gif";
background: src(var(--foo));

但这样写是可以的:

--foo: "http://www.example.com/pinkish.gif";
background: url(var(--foo));

……因为值中的未转义 "(" 会导致解析错误,使整个声明被视为无效丢弃。

未加引号的 url() 语法不能接受 <url-modifier> 参数, 且需要额外的转义: 括号、空白符、单引号 (') 与双引号 (") 出现在 URL 中时都必须用反斜杠转义, 例如 url(open\(parens)url(close\)parens)。 (在带引号的 <string> url() 中,仅需转义换行符和用于包裹字符串的引号。) 视 URL 类型,也可以用 URL 转义字符书写(如 url(open%28parens)url(close%29parens)),详见 [URL]

未加引号 url() 语法的精确定义见 [CSS-SYNTAX-3]

某些 CSS 场景(如 @import)也允许用裸 <string> 表示 <url>,无需函数包装。 在这种情况下,该字符串的行为与包裹同内容的 url() 一致。

例如,以下语句行为完全一致:
@import url("base-theme.css");
@import "base-theme.css";

4.5.1. 相对 URL

为了创建不依赖于资源绝对路径的模块化样式表,建议作者使用相对 URL。 相对 URL(定义见 [URL]) 会通过基准 URL 解析为完整 URL。RFC 3986 第3节定义了规范算法。 对于 CSS 样式表,基准 URL 是样式表本身的 URL,而不是源文档的 URL。 内嵌于文档的样式表,其基准 URL 由其容器关联。

注意: 对于 HTML 文档,基准 URL 是可变的

<url> 出现在属性的计算值中时, 会根据上文描述解析为绝对 URL。 UA 无法解析为绝对 URL 的 URL,其计算值就是指定值。

例如,假设有如下规则:
body { background: url("tile.png") }

位于样式表:

http://www.example.org/style/basic.css

则源文档的 <body> 背景会平铺该 URL 所指向的资源:

http://www.example.org/style/tile.png

无论包含 <body> 的源文档 URL 如何,使用的都是同一图片。

4.5.1.1. 片段 URL

为使元素 ID 引用在 CSS 中无论基准 URL 如何变化或有无 shadow DOM 都能工作,当 <url> 仅包含片段时具备特殊行为。

如果 <url> 的值以 U+0023 井号(#)字符开头, 则该 URL 还会设置 本地 url 标志, 并且是该 URL 树作用域引用,针对该 URL 的 片段

当匹配一个已设置 本地 url 标志<url> 时:

可能需要引用 查找潜在指示元素, 但该定义仅适用于 Document, 不适用于 ShadowRoot

注意: 这意味着此类片段将始终相对于当前文档内容(或样式表所在的节点树,如有 shadow DOM)解析, 而不考虑其他地方的相对 URL 解析方式(如 base 元素改变基准 URL,或外链样式表的相对 URL 按样式表 URL 解析等)。

在下例中,#anchor 会相对于 http://example.com/ 解析,而 #image 则会在 HTML 文档自身元素中解析:
<!DOCTYPE html>
<base href="http://example.com/">
...
<a href="#anchor" style="background-image: url(#image)">link</a>

序列化一个带有 本地 url 标志url() 时, 只需序列化出片段部分。

4.5.2. 空 URL

如果 <url> 的值为空字符串 (如 url("")url()), 则该 url 必须解析为无效资源(类似 about:invalid)。

其计算值为 url("")src(""), 以实际指定为准, 序列化时也应如此。

注意: 这与 Web 平台其他地方嵌入资源的空 url 行为一致, 避免因编辑错误导致 url() 为空而反复请求样式表或主文档, 因为对于 url() 出现的地方,这几乎必然是无效资源。 Web 平台的链接允许空 url, 因此如果 CSS 以后支持超链接控制, 可以在相应场景放宽此限制。

4.5.3. URL 修饰符

<url> 支持指定额外的 <url-modifier>, 用于以某种方式改变 URL 的意义或解释。 <url-modifier> 可以是 <ident>函数式记法

本规范未定义任何 <url-modifier>, 但其他规范可以定义。

注意: 未加引号或未用 url() 包裹的 <url> 不能接受任何 <url-modifier>

4.5.4. URL 处理模型

要从一个 url<url> urlValue获取样式资源, 给定一个 CSSStyleSheet sheet, 一个匹配 RequestDestination 的字符串 destination, 一个 "no-cors" 或 "cors" 的 corsMode, 以及一个接受 response 及 null、failure 或字节流的算法 processResponse
  1. environmentSettingssheet相关设置对象

  2. basesheet样式表基准 URL(如不为 null), 否则为 environmentSettingsAPI 基准 URL[CSSOM]

  3. parsedUrlURL 解析器步骤的结果, 以 urlValueurlbase 为参数。 若算法返回错误,则返回。

  4. req 为新建的 请求,其 urlparsedUrldestinationdestinationmodecorsModeoriginenvironmentSettingsorigincredentials mode 为 "same-origin",use-url-credentials flag 设为 true, clientenvironmentSettingsreferrerenvironmentSettingsAPI 基准 URL

  5. 应用所有适用于该请求的 URL 请求修改步骤

    注意: 本规范未定义任何 URL 请求修改步骤, 但其它规范可定义。

  6. 如果 reqmode 为 "cors", 则将 reqreferrer 设为 sheetlocation[CSSOM]

  7. 如果 sheetorigin-clean flag 被设置, 则将 reqinitiator type 设为 "css"。[CSSOM]

  8. Fetch req, 并将 processresponseconsumebody 设为 processResponse

在解析 CSS 中的 URL 时, URL 解析器encoding 参数 必须省略 (即使用默认 UTF-8), 无论样式表的编码为何。

注意: 换句话说,CSS 中书写的 URL 总是会在 百分号编码非 ASCII 码点时,使用 UTF-8 编码到 URL 对象中(因此当将 URL 值用于如网络请求等场景时总是如此),与样式表本身的编码无关。注意,此过程发生在将样式表解码为 Unicode 码点之后。

5. 数值数据类型

数值数据类型用于表示数量、索引、位置等值。 虽然表达数值(数值部分)本身有多种语法变体, 但指定值计算值不会区分这些变体: 它们代表值的抽象数量,而不是其语法表现形式。

数值数据类型 包括 <integer><number><percentage>, 以及各种带单位数值,如 <length><angle><time><frequency><resolution> 等。

注意:虽然通用带单位数值在此定义, 但其他一些模块还定义了更多数据类型 (如 [css-grid-1] 引入了 fr 单位), 它们的用途更为局部化。

CSS 中数值的精度和支持的范围是由实现定义的, 并且可能会根据值所用的属性或上下文而异。 但在 CSS 规范中, 假定为无限精度和范围。 如果由于实现的范围/精度限制而无法明确支持某个值, 则必须将其转换为实现所支持的最接近的值, 但实现如何定义“最接近”也是由实现定义的。

如果由于超出实现定义的支持范围而必须转换<angle>, 则必须将其裁剪为最接近的 360deg 的倍数。

5.1. 范围限制与范围定义记法

属性可以将数值限制在某个范围内。 如果值超出允许范围, 除非另有说明, 该声明无效,必须被忽略。 可以使用CSS 方括号范围记法[min,max])在数值类型的尖括号内、关键字后标注范围, 表示封闭区间(包含 minmax)。 例如,<integer [0,10]> 表示整数在 010 之间(含端点), <angle [0,180deg]> 则表示角度在 0deg180deg 之间(可为任意单位)。

注意: CSS 值通常不允许开区间,因此只用方括号表示法。

理论上 CSS 支持所有值类型的无限精度和无限范围; 但实际上实现有有限能力。UA 应支持合理有用的范围和精度。 理想情况下无限的范围可用 ∞ 或 −∞ 表示。 例如,<length [0,∞]> 表示非负长度。

如果未标注范围, 无论是通过方括号范围记法还是属性描述, 则假定为 [−∞,]

−∞ 或 ∞ 的值必须无单位书写, 即使该类型通常带单位。 0 可以无单位书写, 即使该类型通常不允许“无单位零” (如 <time>)。

注意: 撰写本规范时, 方括号范围记法尚属新内容; 因此多数 CSS 规范中的范围限制只用文字描述。 (如“负值无效”或“负值不允许”表示 [0,] 范围。) 这些说明同样具有限制效力。

5.2. 整数:<integer> 类型

整数值用 <integer> 表示。

当以字面值书写时, 整数 是一个或多个十进制数字 09,对应于 CSS 语法模块<number-token> 产生式的一个子集。[CSS-SYNTAX-3] 整数的首位数字可前置 -+ 表示正负号。

除非另有说明, 在 CSS 规范中,四舍五入到最接近整数要求在小数部分恰为 0.5 时向 +∞ 方向取整。 (如 1.5 向上取整为 2-1.5 则为 -1。)

5.2.1. <integer> 的计算与组合

除非另有说明, 指定的 <integer>计算值为指定的抽象整数。

插值<integer> 定义为:Vresult = round((1 - p) × VA + p × VB); 即先在实数空间插值(和 <number> 一样),结果再用四舍五入到最接近整数转换为 <integer>

加法<integer> 定义为 Vresult = VA + VB

5.3. 实数:<number> 类型

数值用 <number> 表示, 代表实数,可以带小数部分。

当以字面值书写时, 数值可以是整数, 或零个或多个十进制数字后跟小数点(.)再跟一个或多个十进制数字; 还可在末尾加字母“e”或“E”再跟一个整数,表示科学计数法下的十进制指数。 它对应于 <number-token> 产生式, 见 CSS 语法模块 [CSS-SYNTAX-3]。 与整数一样,数值首位可加 -+ 表示正负号。

<zero> 代表值为 0 的数值字面量。 只要表达式结果为 <number> 且值为 0 (如 calc(0)), 并不匹配 <zero>; 只有字面 <number-token> 匹配。

5.3.1. <number> 的计算与组合

除非另有说明, 指定的 <number>计算值为指定的抽象数值。

插值<number> 定义为 Vresult = (1 - p) × VA + p × VB

加法<number> 定义为 Vresult = VA + VB

5.4. 带单位数值:dimension

通用术语 带单位数值 指带有单位标识符的数值; 用 <dimension> 表示。

当以字面值书写时, 带单位数值 是一个 数值 紧接单位标识符, 单位是一个标识符。 对应 <dimension-token> 产生式, 见 CSS 语法模块 [CSS-SYNTAX-3]。 单位标识符同关键字一样,ASCII 不区分大小写

CSS 用 <dimension> 表示 距离(<length>), 时长(<time>), 频率(<frequency>), 分辨率(<resolution>)等量值。

5.4.1. 兼容单位

序列化计算值[CSSOM]兼容单位(指可用静态比例因子换算的单位,如 pxin 之间的 96:1 比例, 或 font-size 计算值下 empx 之间的比例) 会被转换为唯一的规范单位。 每组兼容单位会指定其中哪个作为规范单位用于序列化。

序列化已解析值(即已用值)时, 所有代表长度的值类型(百分比、数值、关键字等)都视为与长度兼容。 同理,未来返回 已用值 的 API 必须将所有代表距离/时长/频率等的值视为与相关类别 带单位数值兼容,并据此规范化。

5.4.2. 带单位数值的组合

插值兼容的单位带单位数值(比如两个 <length> 值) 定义为 Vresult = (1 - p) × VA + p × VB

加法兼容单位带单位数值,定义为 Vresult = VA + VB

5.5. 百分比:<percentage> 类型

百分比值用 <percentage> 表示, 表示某个参考值的一定比例。

当以字面值书写时, 百分比为一个 数值 紧跟百分号 %。 对应 <percentage-token> 产生式, 见 CSS 语法模块 [CSS-SYNTAX-3]

百分比值总是相对于另一个量(如长度)。 每个允许百分比的属性还会定义百分比所参考的量。 该量可为同一元素其他属性的值、祖先元素属性的值、排版上下文的某个测量 (如 包含块的宽度), 或其他内容。

5.5.1. <percentage> 的计算与组合

除非另有说明 (如 font-size 会将其 <percentage> 值计算为 <length>), 百分比的计算值 就是指定的百分比。

插值<percentage> 定义为 Vresult = (1 - p) × VA + p × VB

加法<percentage> 定义为 Vresult = VA + VB

5.6. 百分比与带单位数值的混合

<percentage> 可在同一带单位数值组件值位置上代表相同量时, 并且可以在 calc() 表达式中与带单位数值组合, 属性语法可用以下便捷记法:

<length-percentage>

等价于 [ <length> | <percentage> ], 其中 <percentage> 会被解析为 <length>

<frequency-percentage>

等价于 [ <frequency> | <percentage> ], 其中 <percentage> 会被解析为 <frequency>

<angle-percentage>

等价于 [ <angle> | <percentage> ], 其中 <percentage> 会被解析为 <angle>

<time-percentage>

等价于 [ <time> | <percentage> ], 其中 <percentage> 会被解析为 <time>

例如,width 属性可以接受 <length><percentage>, 都表示距离量。 这意味着 width: calc(500px + 50%); 是合法的——两个值会转换为绝对长度并相加。 如果包含块宽度为 1000px, 则 width: 50%; 等价于 width: 500pxwidth: calc(50% + 500px) 最终等价于 width: calc(500px + 500px)width: 1000px

另一方面,hsl() 函数的第二和第三参数只能写作 <percentage>。 虽然可以用 calc() 产生式替代, 但只能组合百分比,不能与其他类型混合,如 calc(10% + 20%)

注意: 除非二者兼容,规范不应在语法中用 <percentage> 替代带单位数值。

注意: 未来可按需添加更多 <type-percentage> 产生式。 但不会出现 <number-percentage>,因为 <number><percentage> 不能在 calc() 中组合。

5.6.1. 百分比与带单位数值混合的计算与组合

百分比-带单位混合值的计算值定义如下:

百分比-带单位值组合(如 <length-percentage><frequency-percentage><angle-percentage><time-percentage> 或等价记法)的插值定义为:

加法<percentage> 的定义与插值一致,只是每个分量是相加而非插值

5.7. 比例:<ratio> 类型

比例值用 <ratio> 表示, 代表两个数值的比值。 它通常用来表示宽高比(第一个为宽度,第二个为高度)。

当以字面值书写时, 比例 语法如下:

<ratio> = <number [0,]> [ / <number [0,]> ]?

第二个 <number> 可省略,默认值为 1。 但 <ratio> 序列化时总会写出两个分量。

<ratio> 的计算值为指定的数字对。

如果 <ratio> 中任一数为 0 或无穷, 则代表退化比例(通常不会有效果)。

如果要比较两个 <ratio>, 将第一个数除以第二个数后比较。 例如 3/2 小于 2/1, 因为前者为 1.5,后者为 2。 (换言之,“高”宽高比小于“宽”宽高比。)

5.7.1. <ratio> 的组合

<ratio> 的插值定义为: 先将每个 <ratio> 转为数字(第一个值除以第二个值,如 3 / 2 得 1.5), 再取对数(如 1.5 得约 0.176), 然后对这些值做插值。 插值中间结果再取指数反函数, 最后按“结果为第一个值,第二个为 1”解释为 <ratio>

如任一 <ratio>退化比例, 则无法插值。

例如, 从 5 / 1 线性插值到 3 / 2 的中点, 结果约为比例 2.73 / 1(约为 11 / 4,略高于 3 / 1):
start  = log(5);   // ≈ 0.69897
end    = log(1.5); // ≈ 0.17609
interp = 0.69897*.5 + 0.17609*.5; // ≈ 0.43753
final  = 10^interp; // ≈ 2.73

注意: 用比值的对数插值,保证结果与比例大小无关 (如 5 / 1300 / 200 得到的结果与上例相同), “宽”与“高”对称 (如 1 / 52 / 3 的中点约为 1 / 2.73), 并且无论宽为基准还是高为基准都对称。 这些是许多其它插值策略不具备的特性。

注意: 由于对数的性质, 可用任意对数,例子用的是 base-10, 但如用自然对数 e,插值中间结果不同,最终结果一致。

两个 <ratio> 不支持加法。

6. 距离单位:<length> 类型

长度指距离的度量,在属性定义中用 <length> 表示。 长度是一种带单位数值

对于零长度,单位标识符是可选的 (即可以语法上写作 <number> 0)。 但如果 0 在某属性中既可解析为 <number>,也可解析为 <length> (比如 line-height), 则必须解析为 <number>

属性可以对长度值进行范围限制。 如果值超出允许范围, 声明无效,必须被忽略

虽然某些属性允许负长度值, 这可能会使排版变得复杂,并且可能有实现相关的限制。 如果允许但无法支持负长度值, 必须将其转换为能支持的最接近值。

在无法支持已用长度的情况下, 用户代理必须在实际值中做近似。

长度单位分为两类:相对绝对。 长度的指定值指定长度)由其数值和单位组成。 长度的计算值计算长度)为指定长度解析为绝对长度, 单位不区分: 可以用任意绝对长度单位表示(但序列化时会用它的规范单位,即 px)。

虽然数值的精度支持情况及其如何舍入通常是由实现定义的,但 <length>border-width 及少数其他属性中 会以特定方式舍入, 以确保良好的视觉显示。 (此算法由各属性显式调用。)

若要 将长度对齐为边框宽度,给定 <length> len
  1. 断言:len 为非负数。

  2. 如果 len 是整数个设备像素,不做处理。

  3. 如果 len 大于零但小于 1 个设备像素, 将 len 向上舍入为 1 个 设备像素

  4. 如果 len 大于 1 个设备像素, 向下舍入为最接近的整数个 设备像素

6.1. 相对长度

相对长度单位表示相对于另一个长度的长度。 使用相对单位的样式表更易于在不同输出环境间缩放。

相对单位有:

相对单位简表
单位 相对于
em 元素的字体大小
ex 元素字体的 x 高度
cap 元素字体的大写字母高度
ch 元素字体中窄字形(如“0”)的典型字形进位宽度
ic 元素字体中全角字形(如“水”)的典型字形进位宽度
rem 根元素的字体大小
lh 元素的行高
rlh 根元素的行高
vw 视口宽度的 1%
vh 视口高度的 1%
vi 根元素行内轴方向视口大小的 1%
vb 根元素块轴方向视口大小的 1%
vmin 视口较小维度的 1%
vmax 视口较大维度的 1%

子元素不会继承其父元素指定的相对值; 它们继承计算值

6.1.1. 字体相对长度:emremexrexcaprcapchrchicriclhrlh 单位

字体相对长度指基于字体度量的长度, 可为使用该单位的元素自身字体度量 (局部字体相对长度), 也可为根元素的字体度量 (根字体相对长度)。

单词 Sphinx 注释了多种字体度量:上升部高度、S 的顶端为大写高度、x 的顶端为 x 高度、基线、p 的底部为下降部高度。
常见排版度量
em
等于使用该单位元素的 font-size 属性的计算值。
例如:
h1 { line-height: 1.2em }

表示 h1 元素的行高 将比其字体大小大 20%。 另一方面:

h1 { font-size: 1.2em }

表示 h1 元素的字体大小 比其继承的字体大小大 20%。

rem
等于根元素上 em 单位的计算值。
ex
等于首选字体的实际 x 高度 [CSS3-FONTS]。 x 高度通常等于小写 x 的高度。 但即使字体不含 "x" 也有 ex 的定义。 x 高度可有多种方式获得。 有些字体提供可靠的 x 高度度量。 若无可靠度量,UA 可用小写字形高度近似。 一种启发是取小写 "o" 超出基线的距离,再用其外框顶减去该值。 如无法或不便确定 x 高度,必须假定为 0.5em。
rex
等于根元素上 ex 单位的值。
cap
等于首选字体的实际大写高度 [CSS3-FONTS]。 大写高度约等于大写拉丁字母的高度。 但即使不含拉丁字母也有 cap 单位。 cap 高度可多种方式获得。 有些字体有可靠 cap 高度度量。 若无可靠度量,UA 可用大写字形高度近似。 一种启发是取大写 “O” 超出基线的距离,再用其外框顶减去该值。 如无法或不便确定 cap 高度,应使用字体的 ascent。
rcap
等于根元素上 cap 单位的值。
ch
表示欧洲字母数字的典型进位宽度,为该字体中 “0” (U+0030) 的实际进位宽度。 (进位宽度指字形在元素行内轴方向的 advance width 或 height。)

注意: 此度量为近似值(等宽字体下为精确值), 方便基于字形数估算宽度。

注意: 字形进位宽度受书写模式、文本方向、字体设置、text-transform 及其他影响字形选择或方向的属性影响。

如无法或不便确定 “0” 的度量, 应假定宽为 0.5em,高为 1em。 因此 ch 单位一般为 0.5em, 竖排时为 1em (如 writing-modevertical-rlvertical-lrtext-orientationupright)。

rch
等于根元素上 ch 单位的值。
ic
表示 CJK 字母的典型进位宽度,为所用字体中 “水” (U+6C34) 的实际 进位宽度

注意: 这个度量通常是精确值(极少数全角字形比例字体中为近似值), 便于基于字形数估算宽度。

如无法或不便确定汉字进位宽度,应假定为 1em。

ric
等于根元素上 ic 单位的值。
lh
等于元素 line-height 属性的计算值, 其中 normal 通过仅用首选字体的度量转为绝对长度。
rlh
等于根元素上 lh 单位的值。

注意:height 属性指定 lhrlh 单位, 并不能让作者控制实际行数, 这些单位只用于理论上理想空行的长度计算; 实际行盒大小因内容而异。 如需限制元素实际行数,可用 max-lines 属性。

在元素上用于 font-* 属性值时, 字体相对长度 以父元素的计算度量为基准——如无父元素,则以 fontline-height 属性的初始值度量。 同理, lhrlh 单位用于 line-heightfont-* 属性值时, 以父元素的 line-height 和字体度量为基准——如无父元素,则以 fontline-height 的初始值度量。 (其他字体相对长度在 line-height 属性中依然基于元素自身度量。)

在非元素上下文中使用(如 媒体查询), 字体相对长度 单位以 fontline-height 属性的初始值度量为基准。 同理,文档无根元素时, 根字体相对长度fontline-height 的初始值度量解析。

注意: chic 等字体相对单位可能会触发字体下载, 如所需字体尚未加载。

字体相对长度的计算不考虑字形变形。

有些用户代理允许用户为文档字体大小加以限制,如设置最小字体以保证可读性。 这些限制只应用于受影响属性的已用值不得影响属性中 字体相对长度的解析。 但在其他场景(如 媒体查询), 若限制影响字体度量, 则会影响 字体相对长度的解析。

注意: 一般来说,尊重用户偏好(如最小字体)是有益的; 例如 (min-width: 40em) 媒体查询用实际字体大小对齐有用。 但让这些偏好影响元素属性中的字体相对长度,不符合 Web 兼容性; 太多页面要求这些单位是指定 font-size 的精确倍数, 而不是应用用户偏好后的实际字体大小。

有些用户代理对表单控件的 line-height 值有限制。 这些限制对 lhrlh 单位没有影响。 但对子元素的影响为由实现定义

6.1.2. 视口百分比长度:*vw*vh*vi*vb*vmin*vmax 单位

视口百分比长度相对于初始包含块的大小—— 即基于视口大小(连续媒体)或页面区域分页媒体)的大小。 改变初始包含块的宽高时,它们会相应缩放。

6.1.2.1. 大、小与动态视口尺寸

视口百分比单位有四种变体, 分别对应三种(可能相同)视口尺寸概念。

large viewport
大视口百分比单位lv*) 和 默认视口百分比单位v*) 以 大视口尺寸为基准: 该视口尺寸假定所有UA可动态展开/收起的界面都已收起。 这样作者可确保内容填满整个视口, 但这些内容在界面展开时可能会被遮挡。

大视口百分比单位的尺寸是固定的(因此稳定),除非视口本身调整。

例如,在手机上, 屏幕空间有限, 浏览器常在用户滚动页面后隐藏标题栏和地址栏。 大视口百分比单位相对于这些界面收起后的空间, 所以用这些单位的内容在界面收起时会填满整个可见页面。 但界面显示时,这些单位定位或大小的内容可能会被遮挡。
small viewport
小视口百分比单位sv*) 以 小视口尺寸为基准: 该视口尺寸假定所有UA可动态展开/收起的界面都已展开。 这样作者可确保内容即使界面展开也不会被遮挡, 但界面收起时内容可能不会填满视口。

小视口百分比单位的尺寸是固定的(因此稳定),除非视口本身调整。

例如,height: 100svh 的元素, 在所有 UA 动态界面显示时会完美填满屏幕,不会内容被遮挡。

但这些界面收起后,该元素周围会有额外空间。 小视口百分比单位通常更安全, 但用户与页面交互后可能布局不最优。

dynamic viewport
动态视口百分比单位dv*) 以 动态视口尺寸为基准: 即考虑动态展开/收起的所有UA界面后的视口大小。 这样作者可确保内容无论界面在否都能完全适配视口。

动态视口百分比单位的尺寸即使视口本身不变也不稳定。 使用这些单位可能导致内容在滚动等操作中随时重排, 可能影响用户体验和性能。

UA 不要求在界面动画(展开/收起)时对 动态视口百分比单位 进行动画, 可以直接按界面完全展开或收起时计算单位。 (建议 UA 在此期间假定完全收起尺寸。)

某一界面的展开/收起 (A) 是否导致所有 视口百分比长度(及初始包含块)同时改变, 还是 (B) 只体现在 大视口尺寸小视口尺寸 的差异, 主要由 UA 决定。 但:

无论何种情况, 若 overflowscrollbar-gutter根元素任一轴上 会无条件导致滚动条出现(或预留空间) (如 overflow: scroll,但不是 overflow: auto), 该轴的 视口百分比长度计算值 会按初始包含块减少。 否则, 且在 媒体查询下始终如此, 视口百分比长度假定无滚动条 (即使与初始包含块不一致)。

注意: overflowbody 元素 上有时会影响 根元素 是否出现滚动条。 但这不会影响视口单位大小。

6.1.2.2. 各种视口相关单位

视口百分比长度单位包括:

vw
svw
lvw
dvw
分别等于 大视口尺寸小视口尺寸大视口尺寸动态视口尺寸 宽度的 1%。
下例中,若视口宽为 200mm, h1 元素的字体大小将为 16mm (即 (8×200mm)/100)。
h1 { font-size: 8vw }
vh
svh
lvh
dvh
分别等于 大视口尺寸小视口尺寸大视口尺寸动态视口尺寸 高度的 1%。
vi
svi
lvi
dvi
分别等于盒子的 大视口尺寸小视口尺寸大视口尺寸动态视口尺寸行内轴 上的大小的 1%。
vb
svb
lvb
dvb
分别等于盒子的 大视口尺寸小视口尺寸大视口尺寸动态视口尺寸块轴 上的大小的 1%。
vmin
svmin
lvmin
dvmin
等于 *vw*vh 中较小者。
vmax
svmax
lvmax
dvmax
等于 *vw*vh 中较大者。

注意: 最初(无前缀)视口单位定义为相对于初始包含块, 在连续媒体中总是与唯一视口尺寸一致。 浏览器 chrome 在滚动中动态变化是后来的发明,大多数 UA 按 Safari 的实现将这些单位映射到较大尺寸。 这种定义在很多场合更美观,但也可能遮挡关键内容(如工具栏、头部、底部)。 因此这种映射是否最佳尚无定论,早期规范允许 UA 选择默认单位的映射。 但目前为 Web 兼容性,假定必须映射到大视口百分比单位

无元素或尚未样式化时(如评估媒体查询), *vi*vb 单位用 writing-mode 属性的初始值决定各自的轴。

6.2. 绝对长度:cmmmQinptpcpx 单位

绝对长度单位彼此有固定关系,并锚定到物理度量。 主要用于已知输出环境时。 绝对单位包括 物理单位incmmmptpcQ) 和 视觉角度单位(像素单位)px):

单位 名称 换算关系
cm 厘米 1cm = 96px/2.54
mm 毫米 1mm = 1cm 的 1/10
Q 四分之一毫米 1Q = 1cm 的 1/40
in 英寸 1in = 2.54cm = 96px
pc 派卡(pica) 1pc = 1in 的 1/6
pt 点(point) 1pt = 1in 的 1/72
px 像素 1px = 1in 的 1/96
h1 { margin: 0.5in }      /* 英寸  */
h2 { line-height: 3cm }   /* 厘米 */
h3 { word-spacing: 4mm }  /* 毫米 */
h3 { letter-spacing: 1Q } /* 四分之一毫米 */
h4 { font-size: 12pt }    /* 点 */
h4 { font-size: 1pc }     /* 派卡 */
p  { font-size: 12px }    /* px */

注意: 出版领域的长度有时写作 2p3, 表示 2 派卡 3 点的长度。 在 CSS 中可写作 calc(2pc + 3pt)(参见 § 10.1 基本算术:calc())。

所有绝对长度单位都是兼容的, 而 px 是其规范单位

对于 CSS 设备,这些尺寸的 锚定单位可通过以下任一方式:

  1. 物理单位与物理度量相关联,或
  2. 像素单位参考像素相关联。

对于典型阅读距离下的印刷介质, 锚定单位应为物理单位(英寸、厘米等)。 对于屏幕介质(包括高分辨率设备)、低分辨率设备及其它特殊距离设备, 推荐用 锚定单位像素单位。 这类设备建议 像素单位 指向最接近参考像素的整数个设备像素

注意:锚定单位像素单位时, 物理单位可能与实际物理尺寸不符。 若 锚定单位物理单位像素单位可能无法与整数个设备像素精确对应。

注意: 本规范对像素单位物理单位的定义不同于 CSS1、CSS2 早期版本。 早期版本中,像素单位物理单位没有固定比例: 物理单位始终与物理尺寸相关,而像素单位会随参考像素变化。 (此变更主要是因大量现有内容假定 96dpi,改变会严重破坏兼容性。)

注意: 单位ASCII 不区分大小写,序列化为小写,例如 1Q 序列化为 1q。

参考像素 指在 96dpi 设备上、与读者一臂距离处的一个像素所对应的可视角度。 臂长约 28 英寸时,可视角约 0.0213 度。 按臂长距离阅读时,1px 约为 0.26 mm(1/96 英寸)。

下图展示了视距对参考像素大小的影响: 71 cm(28 英寸)时,参考像素为 0.26 mm, 3.5 m(12 英尺)时,参考像素为 1.3 mm。

该图示说明像素的定义取决于与用户距离。图中用户分别注视两个平面,一个距用户 71 cm,一个 3.5 m。投射的锥体在第一个平面投影像素高 0.26 mm,在第二个平面高 1.4 mm。
显示视距增加时像素也要变大

下图展示了设备分辨率对像素单位的影响:1px*1px 区域在低分辨率设备(如普通显示器)由一个点覆盖,在高分辨率设备(如打印机)由 16 个点覆盖。

该图示说明参考像素与设备像素的关系。左边高分辨率激光打印机输出,右边低分辨率显示器。激光打印机一个参考像素用 16 个点实现,显示器用 1 个点。
显示高分辨率设备上需更多设备像素(点)覆盖 1px*1px 区域

设备像素 是设备输出上能显示全色域的最小面积单元。 常见彩色屏幕中为包含红绿蓝子像素的正方形或矩形区域。 许多非传统输出可能模糊此定义,如某些颜色分辨率更高的设备。 这些设备仍会暴露等价的“设备像素”概念。

7. 其他数量单位

7.1. 角度单位:<angle> 类型及 deggradradturn 单位

角度值是<dimension>,用 <angle> 表示。 角度单位标识符包括:

deg
度。一个完整圆有 360 度。
grad
梯度,也称为“gon”或“grade”。一个完整圆有 400 梯度。
rad
弧度。一个完整圆有 2π 弧度。
turn
圈。一个完整圆为 1 turn。

例如,直角可写作 90deg100grad0.25turn 或约 1.57rad

所有 <angle> 单位都是兼容的deg 是它们的规范单位

按惯例, 当角度在 CSS 中表示方向时, 通常解释为 方位角, 即 0deg 是屏幕“上方”或“北方”, 角度增大顺时针方向增加(例如 90deg 是“右”或“东”)。

例如,在 linear-gradient() 函数中, 用于确定渐变方向的 <angle> 就按方位角解释。

注意: 出于兼容性原因, 某些 <angle> 的用法允许裸 0 表示 0deg。 但这不是通用规则,未来也不会出现在 <angle> 类型的新用法中。

7.2. 时长单位:<time> 类型及 sms 单位

时间值是带单位数值,用 <time> 表示。 时间单位标识符包括:

s
秒。
ms
毫秒。1 秒等于 1000 毫秒。

所有 <time> 单位都是兼容的s 是它们的规范单位

属性可以限制时长值的取值范围。 如果值超出允许范围, 声明无效,必须被忽略

7.3. 频率单位:<frequency> 类型及 HzkHz 单位

频率值是带单位数值,用 <frequency> 表示。 频率单位标识符包括:

Hz
赫兹。表示每秒发生的次数。
kHz
千赫兹。1 千赫兹等于 1000 赫兹。

例如,表示声音音高时,200Hz(或 200hz)是低音,6kHz(或 6khz)是高音。

所有 <frequency> 单位都是兼容的hz 是它们的规范单位

注意: 单位ASCII 不区分大小写,序列化为小写,如 1Hz 序列化为 1hz。

7.4. 分辨率单位:<resolution> 类型及 dpidpcmdppx 单位

分辨率单位是带单位数值,用 <resolution> 表示。 分辨率单位标识符包括:

dpi
每英寸点数。
dpcm
每厘米点数。
dppx
x
px 单位的点数。

<resolution> 单位表示图形表现中单个“点”的大小,即每个 CSS incmpx 中包含多少个点。 用法见如 resolution 媒体查询([MEDIAQ])或 image-resolution 属性([CSS3-IMAGES])。

所有 <resolution> 单位都是兼容的dppx 是它们的规范单位

<resolution> 的取值范围始终排除负值,此外还可有其他显式范围限制。

注意,由于 CSS in 与 CSS px 的 1:96 固定比例,1dppx 等价于 96dpi。 这与 CSS 下图片的默认分辨率对应,详见 image-resolution

下例 @media 规则用 Media Queries [MEDIAQ] 为每个 CSS px 单位用两个及以上设备像素的设备分配特殊样式:
@media (min-resolution: 2dppx) { ... }

8. 其他地方定义的数据类型

某些数据类型在其各自的模块中定义。 本例介绍了多个规范中常用的一些类型。

8.1. 颜色:<color> 类型

<color> 数据类型在 [CSS-COLOR-4] 中定义。 UA 必须按照该规范解释 <color>

8.1.1. <color> 的组合

插值<color>CSS Color 4 §  12. 色彩插值 中定义。 插值在预乘色彩间进行,详见 CSS Color 4 § 12.3 含 Alpha 的插值

<color> 类型不可加

注意: CSS 工作组欢迎反馈<color> 求和的用例,将来有可能使 <color> 支持可加性。

8.2. 图像:<image> 类型

<image> 数据类型见 [CSS3-IMAGES]。 支持 CSS Images Level 3 或更高的 UA 必须按规范解释 <image>。 不支持 CSS Images Level 3 的 UA 必须将 <image><url> 处理。

8.2.1. <image> 的组合

注意: <image> 的插值在 CSS Images 3 § 6 插值 中定义。

图像不可加

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

<position> 值用于指定对象区域(如背景图片) 在定位区域(如背景定位区域)内的位置。 它的计算与解释方式同 background-position[CSS3-BACKGROUND]

<position> = [
  [ left | center | right | top | bottom | <length-percentage> ]
|
  [ left | center | right ] && [ top | center | bottom ]
|
  [ left | center | right | <length-percentage> ]
  [ top | center | bottom | <length-percentage> ]
|
  [ [ left | right ] <length-percentage> ] &&
  [ [ top | bottom ] <length-percentage> ]
]

注意: background-position 属性还接受三值语法。 但这已被通用上禁用,因为与其他长度或百分比成分组合时会造成解析歧义。

8.3.1. <position> 的解析

当与其他关键字、<length><percentage> 并列出现于语法中时,<position>贪婪地解析,尽可能多地消耗成分。

例如,transform-origin 定义了三维位置,实质为 <position> <length>?left 50px 会被解析为二值 <position>(省略 z 分量); 而 top 50px 会被解析为单值 <position> 后跟一个 <length>

8.3.2. <position> 的序列化

序列化 指定值<position> 时:

只指定一个成分时:
  • 自动补上 center 关键字,序列化为二值形式。

指定两个成分时:
  • 关键字按关键字序列化。

  • <length-percentage> 按原样序列化。

  • 成分序列化顺序为先水平后垂直。

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

  • 成分序列化顺序为先水平后垂直。

注意: <position> 值序列化时不写作单值, 即使单值行为一致, 这样避免在某些语法中(如 <position> 紧跟 <length>,如 transform-origin)产生解析歧义。

注意: 计算值总是序列化为两个偏移(不带关键字), 因为计算值不保留语法细节。

8.3.3. <position> 的组合

插值 <position> 的定义为独立对每个成分(x, y)插值,并以左上角为基准归一化为 <length-percentage>

加法 <position> 也是独立对每个成分(x, y)相加,并以左上角为基准归一化为 <length-percentage>

9. 函数式记法

函数式记法是一种组件值类型, 可以表示更复杂的类型或触发特殊处理。 其语法以函数名开头, 紧接左括号 (即 <function-token>), 后跟参数, 最后右括号结尾。 与关键字一样,函数名ASCII 不区分大小写括号内可有空白,但不是必须的。 函数可以有多个参数, 参数格式类似 CSS 属性值。 见§ 2.6 函数式记法定义

注意: 部分旧有函数式记法,如 rgba(),会多余地使用逗号, 但一般情况下逗号只用于分隔列表项, 或避免语法歧义。 如果逗号用于分隔参数,逗号前后空白可有可无。

background: url(http://www.example.org/image);
color: rgb(100, 200, 50 );
content: counter(list-item) ". ";
width: calc(50% - 2em);

下方定义了数学函数。 其他函数式记法在各自模块中定义; 例如 <color> 函数见 [CSS-COLOR-4][CSS-COLOR-5]

10. 数学表达式

数学函数calc()clamp()sin() 等本章定义的函数) 允许用数学表达式书写 CSS 数值。

数学函数表示一种数值, 可以是:

……或<length-percentage> 等混合类型,并可在任何该类型值可用处使用。

10.1. 基础算术:calc()

calc() 函数是一种数学函数,可对数值进行加(+)、减(-)、乘(*)、除(/)和括号内的基础算术运算。

calc() 函数包含一个 计算, 即一串值与运算符交错组成的序列,可用括号分组 (符合 <calc-sum> 语法), 表示采用标准运算符优先级规则 (*/ 优先于 +-,其余左到右)求值的结果。 calc() 函数表示其内部计算的结果。

计算的组成可为字面值 (如 5px), 其他数学函数, 或其他表达式(如 var()), 只要能求值为有效参数类型(如 <length>)。

数学函数可以组合不同单位的值。 下例作者希望每个 section 的外边框盒占据 1/3 空间, 于是从 100%/3 开始, 再减去元素的边框和外边距。 (box-sizing 可自动处理边框和内边距, 但如要包括外边距,需用 数学函数。)

section {
  float: left;
  margin: 1em; border: solid 1px;
  width: calc(100% / 3 - 2 * 1em - 2 * 1px);
}

类似地,下例中的渐变色带只在元素的第一个和最后一个 20px 处出现颜色过渡:

.fade {
  background-image: linear-gradient(silver 0%, white 20px,
                                    white calc(100% - 20px), silver 100%);
}

数学函数也可用于让数值表达更自然易读, 而不是晦涩的小数。 例如,下例将 font-size 设为正好 35em 填满视口, 保证无论屏幕大小如何,屏幕内容始终大致一样多。

:root {
  font-size: calc(100vw / 35);
}

功能上这等价于直接写 font-size: 2.857vw, 但前者意图(即 35em 填满视口)对代码阅读者更清晰, 后者读者须反推 2.857 就是 100/35。

运算符遵循标准数学优先级:calc(2 + 3 * 4) 等于 14,不是 20

括号可用来调整优先级:calc((2 + 3) * 4) 等于 20

括号和嵌套 calc() 等价; 上述表达式可写作 calc(calc(2 + 3) * 4)。 这在用 var() 逐步组合值时很有用, 例如:

.aspect-ratio-box {
  --ar: calc(16 / 9);
  --w: calc(100% / 3);
  --h: calc(var(--w) / var(--ar));
  width: var(--w);
  height: var(--h);
}

虽然 --ar 可以直接写作 --ar: (16 / 9);,但 --w 既单独用(在 width)也作为 calc() 组件(在 --h), 所以它也必须用完整 calc() 函数形式。

10.2. 比较函数:min()max()clamp()

min()max()clamp() 比较多个计算,返回其中一个的值。

min()max() 函数 包含一个或多个逗号分隔的计算, 分别返回最小(最负)或最大(最正)值。

clamp() 接收三个计算——最小值、中值、最大值——返回中值, 按最小值和最大值裁剪,冲突时优先最小值。 (即 clamp(MIN, VAL, MAX) 等价于 max(MIN, min(VAL, MAX)))。

最小值或最大值 (甚至可两者都用) 可以用关键字 none, 表示该侧裁剪。 (如 clamp(MIN, VAL, none) 等价于 max(MIN, VAL)clamp(none, VAL, MAX) 等价于 min(VAL, MAX)clamp(none, VAL, none) 等价于 calc(VAL)。)

三者参数计算可为任意 <number><dimension><percentage>, 但类型必须一致,否则函数无效; 结果类型即为一致类型

min()max()clamp() 可确保值不超过“安全”极限: 例如用视口单位设置font-size的“响应式字号”时, 仍可设定最小值保证可读性:

.type {
  /* 字号为 vw 和 vh 平均数的10倍,但不得小于12px */
  font-size: max(10 * (1vw + 1vh) / 2, 12px);
}

注意: 每个参数都可用完整数学表达式,无需嵌套 calc()! 你也可以传多个参数,适用于多重约束。

min()/max() 时常见困惑是,用 max() 实际上是给某值加最小值 (如 min-width 实际用的是 max()), 而 min() 则用作限定最大值; 很容易用错,比如试图用 min() 加最小值。 用 clamp() 代码更直观, 因为它把值夹在最小和最大之间:
.type {
  /* 字号限定在 12px 和 100px 之间 */
  font-size: clamp(12px, 10 * (1vw + 1vh) / 2, 100px);
}

或者只想限定最小值,允许字号随意变大:

.type {
  /* 字号至少 12px */
  font-size: clamp(12px, 10 * (1vw + 1vh) / 2, none);
}
注意 clamp() 与 CSS 其它惯例一致, 若最小值与最大值顺序颠倒,以最小值为准。 即 clamp(100px, ..., 50px) 会返回 100px,超过其“最大值”。

如需其他裁剪逻辑,可结合 clamp()min()max()

让 MAX 优先生效:

clamp(min(MIN, MAX), VAL, MAX)。 若想避免重复 MAX 计算, 可反过来嵌套函数——min(MAX, max(MIN, VAL))

让 MAX 和 MIN“互换”顺序:

clamp(min(MIN, MAX), VAL, max(MIN, MAX))。 不幸的是,这没法避免 MIN 和 MAX 重复。

10.3. 分步值函数:round()mod()rem()

分步值函数 round()mod()rem(),都会根据另一个“步长值”以不同方式转换给定值。

round(<rounding-strategy>?, A, B?) 函数包含一个可选的舍入策略和两个计算参数A和B,并返回A的值,按照舍入策略对A进行舍入,舍入到最接近A的B的整数倍(可以是大于或小于A)。参数 calculations 可以解析为任何 <number><dimension><percentage>,但必须具有一致类型,否则函数无效;结果的类型将是 一致类型

如果A恰好等于B的整数倍,round()精确返回A(如果相关,会保留A是0⁻还是0⁺)。 否则,B的两个整数倍可能“最接近”A,lower B 更接近 −∞,upper B 更接近 +∞。以下<rounding-strategy>用于决定如何选择它们:

nearest

选择lower Bupper B中与A绝对差值最小的一个。如果两者差值相等(A正好在两者之间),选择upper B

up

选择upper B

down

选择lower B

to-zero

选择lower Bupper B中与0绝对差值最小的那个。

如果 lower B 为零,则其值为 0⁺;如果 upper B 为零,则其值为 0⁻。

如果省略 <rounding-strategy>,则默认为 nearest。 (即四舍五入到最接近的整数。) 如果A的类型 匹配 <number>, 则B可以省略,默认值为1;否则省略B是无效的。

CSSOM 需要规定其舍入方式,CSS函数默认最好也采用一致的舍入方式。应该使用哪种行为?[Issue #5689]

不同于 JavaScript 这类拥有自然“精度”(整数)可用于舍入的语言,CSS值没有这样的精度,因为值可以用许多不同的兼容单位书写。因此,精度必须被显式给出;要将宽度舍入到最接近的 50px,可以写作 round(var(--width), 50px)

注意: JavaScript 和其他编程语言有时会将不同的舍入策略分为不同的舍入函数。JS的 Math.floor() 等价于CSS的 round(down, ...);JS的 Math.ceil() 等价于CSS的 round(up, ...);JS的 Math.trunc() 等价于CSS的 round(to-zero, ...);JS的 Math.round() 等价于CSS的 round(nearest, ...),或直接写 round(...)

注意: <rounding-strategy> 关键字与 block-step-size 中的关键字一致,行为也相同。 (block-step-size 只是缺少 to-zero;由于块大小始终为非负,to-zerodown 是一致的。)

取模函数 mod(A, B)rem(A, B) 也包含两个 计算 参数A与B,并返回A与最接近A的B的整数倍(大于或小于A均可)之间的差值。 参数 calculations 可解析为 <number><dimension><percentage>,但必须有相同类型,否则函数无效;结果的类型与参数相同,类型为参数类型

这两个函数非常相似,实际上当两个参数都为正或都为负时,返回结果完全一致:函数值等于A减去能使结果在零与B之间的B的整数倍。(具体来说,区间包含零但不包含B。更精确地说,如果B为正,则区间从0⁺开始,如果B为负,则从0⁻开始。)

例如,mod(18px, 5px) 的值为 3px,因为 18px 减去 5px * 3 等于 3px,这是唯一处于 0px3px 之间的值。

类似地,mod(-140deg, -90deg) 的值为 -50deg,因为 -140deg 加上 -90deg * 1 等于 -50deg,这是唯一处于 0deg-90deg 之间的值。

将这些示例用 rem() 计算,结果完全相同。

当A值与B步长符号相反时,这两个函数的行为会不同:mod()(即“模”)依然选择能让结果在零与B之间的B的整数倍(保证结果要么为零,要么与B同号,不与A同号),而rem()(即“余数”)选择让结果在零与-B之间的B的整数倍,避免改变值的符号。

例如,mod(-18px, 5px) 的值为 2px-18px5px * 4 等于 2px,位于 0px5px 之间。

rem(-18px, 5px) 的值为 -3px-18px5px * 3 等于 -3px,它与 -18px 同号,且位于 0px-5px 之间。

同理,mod(140deg, -90deg) 的值为 -40deg140deg-90deg * 2,落在 0deg-90deg 之间),但 rem(140deg, -90deg) 的值为 50deg

我应该选择 mod() 还是 rem()

通常,使用该操作的用户可控制步长值(B),而是在修改未知值A。因此,通常更期望结果在0与B之间,而不管A的符号如何,这时应选择 mod()

比如,如果作者想知道一个长度是否是偶数或奇数像素,mod(A, 2px) 会返回 0px1px(假设该值本来就是整数像素),与A的正负无关。而 rem(A, 2px),如果A是偶数像素会返回0px,但如果是奇数像素,则会返回1px-1px,取决于A的正负。

不过,也会有相反的需求,因此提供了 rem() 以满足这些场景。此外,rem() 的行为与JavaScript的 % 运算符一致,所以如果希望CSS与JS代码完全匹配,rem() 就很有用。

注意: mod()rem() 也可以直接用其它函数定义:mod(A, B) 等同于 calc(A - sign(B)*round(down, A*sign(B), B))(可以理解为B为正时是round(down),B为负时是round(up)),而 rem(A, B) 等同于 calc(A - round(to-zero, A, B))。(但这些表达式并不总能正确处理0⁺和0⁻,因为0⁻的加法语义不是交换的。)

10.3.1. 参数取值范围

round(A, B) 中,如果B为0,结果为NaN。如果A和B都为无穷大,结果为NaN。

如果A为无穷大但B为有限值,结果为与A相同的无穷大。

如果A为有限值但B为无穷大,则结果取决于 <rounding-strategy> 以及A的符号:

nearest
to-zero

如果A为正或0⁺,返回0⁺;否则返回0⁻。

up

如果A为正(非零),返回+∞。如果A为0⁺,返回0⁺。否则返回0⁻。

down

如果A为负(非零),返回−∞。如果A为0⁻,返回0⁻。否则返回0⁺。

mod(A, B)rem(A, B) 中,如果B为0,结果为NaN。如果A为无穷大,结果为NaN。

仅在 mod(A, B) 中,如果B为无穷大且A与B符号相反(包括符号相反的零),结果为NaN。

注意: 其他所有“B为无穷大”的情况都是有效的,直接返回A。

10.4. 三角函数:sin()cos()tan()asin()acos()atan()atan2()

三角函数——sin()cos()tan()asin()acos()atan()atan2(),用于计算各种基本三角关系。

sin(A)cos(A)tan(A) 函数都包含一个 计算,其值必须为 <number><angle>,并将其参数值视为弧度来计算其对应的三角函数值。 (即 sin(45deg)sin(.125turn)sin(3.14159 / 4) 均表示相同的值,大约为 .707。) 它们都表示 <number>,返回类型会与输入 计算 的类型保持一致sin()cos() 的返回值总在 −1 到 1 之间,而 tan() 的返回值可在 −∞ 到 +∞ 之间。(关于数学函数如何处理∞,详见§ 10.9 类型检查。)

asin(A)acos(A)atan(A) 是“反”或“反三角”函数,对应其“普通”三角函数的反函数。 它们都包含一个 计算,值必须为 <number>,并计算其对应的反三角函数值,返回值视为弧度数,表示为 <angle>,返回类型与输入 计算 的类型保持一致asin() 返回的角度需规范化到 [-90deg, 90deg] 范围内; acos() 返回的角度需在 [0deg, 180deg]; atan() 返回的角度需在 [-90deg, 90deg]。

atan2(A, B) 函数包含两个用逗号分隔的 计算 参数A和B。A和B可为 <number><dimension><percentage>,但必须有一致类型,否则函数无效。该函数返回正X轴与点(B, A)之间的 <angle>,返回类型与输入 计算 的类型保持一致。返回角度必须规范到区间(-180deg, 180deg](即大于-180deg,小于等于180deg)。

注意: atan2(Y, X) 一般等价于 atan(Y / X),但当点的分量可能为负时会给出更准确的答案。atan2(1, -1)(点为(-1, 1))返回 135degatan2(-1, 1)(点为(1, -1))返回 -45deg。而 atan(1 / -1)atan(-1 / 1) 都返回-45deg,因为内部计算结果都是-1

10.4.1. 参数取值范围

sin(A)cos(A)tan(A) 中,如果A为无穷大,结果为NaN。(关于数学函数如何处理NaN,详见§ 10.9 类型检查。)

sin(A)tan(A) 中,如果A为0⁻,结果为0⁻。

tan(A) 中,如果A为渐近值(如 90deg270deg 等),数值结果为实现自定。如果实现能精确表示这些输入,90deg + N*360deg 的渐近处返回+∞,在 -90deg + N*360deg 处返回−∞,但实现不要求必须能精确表示这些输入(如果不能,将返回其能表示的最接近输入的正确数值结果)。作者不得依赖 tan() 在这些输入下返回特定值。

为什么这些值是实现自定

正切函数在其渐近点是不连续的:它在一侧趋向正无穷,在另一侧趋向负无穷,且在渐近点本身没有定义。

此外,实现能否精确表示这些渐近点,取决于内部如何存储和处理角度;以度为单位时这些值很简单(如90deg),但以弧度表示时这些值是超越数(如pi / 2),无法精确表示。因此,即便要定义特定行为也比较困难;如果实现内部用弧度,需要做模糊匹配,才能在输入足够接近渐近点时返回预期结果。

Web 另一主流语言 JavaScript,这些函数只接受弧度,因此也无法精确遇到渐近点(大多数其他语言亦如此)。JS中写代码时也无法依赖这些值的特定行为,CSS的需求也不太可能有本质不同。

对于能精确表示渐近点的实现,建议的行为可以保证与 atan() 函数的互相转换:tan(atan(X))atan(tan(X)) 都会返回(近似)X。也就是说,在 atan() 的支持输出范围内,函数是连续的。

asin(A)acos(A) 中,如果A小于-1或大于1,结果为NaN。

acos(A) 中,如果A恰好为1,结果为0。

asin(A)atan(A) 中,如果A为0⁻,结果为0⁻。

atan(A) 中,如果A为+∞,结果为 90deg;如果A为−∞,结果为 -90deg

atan2(Y, X) 中,下面的表格给出了所有特殊参数组合的结果:

X
−∞ -finite 0⁻ 0⁺ +finite +∞
Y −∞ -135deg -90deg -90deg -90deg -90deg -45deg
-finite -180deg (正常) -90deg -90deg (正常) 0⁻deg
0⁻ -180deg -180deg -180deg 0⁻deg 0⁻deg 0⁻deg
0⁺ 180deg 180deg 180deg 0⁺deg 0⁺deg 0⁺deg
+finite 180deg (正常) 90deg 90deg (正常) 0⁺deg
+∞ 135deg 90deg 90deg 90deg 90deg 45deg

注意: 所有这些行为都旨在与大多数编程语言的“标准”定义一致,尤其是与JS中的实现一致。

10.5. 指数函数:pow()sqrt()hypot()log()exp()

指数函数——pow()sqrt()hypot()log()exp()——用于计算其参数的各种指数运算。

pow(A, B) 函数包含两个用逗号分隔的 计算参数A和B,两者都必须解析为<number>,返回A的B次幂,结果为 <number>。输入的 计算必须有一致类型,否则函数无效;结果类型为 一致类型

sqrt(A) 函数包含一个 计算参数,必须解析为<number>,返回该值的平方根,结果为 <number>,返回类型与输入 计算的类型保持一致。(sqrt(X)pow(X, .5) 基本等价,仅在部分错误处理上有区别;sqrt() 是常用函数,因此单独提供。)

hypot(A, …) 函数包含一个或多个用逗号分隔的 计算参数,返回以每个 计算为分量的N维向量的长度。(即其参数平方和的平方根。)参数 calculations 可解析为 <number><dimension><percentage>,但必须有一致类型,否则函数无效;结果类型为 一致类型

为什么 hypot() 允许带单位的维度值,而 pow()sqrt() 只接受数字?

你可以写出像 hypot(30px, 40px) 这样的表达式,解析结果是 50px,但不能写 sqrt(pow(30px, 2) + pow(40px, 2)),虽然在大多数数学系统中这两者是等价的。

原因有二:一是幂运算的数值精度,二是作者的预期冲突。

首先,数值精度。对于类型匹配<length> 这样的CSS产生式,单位的指数必须精确为1。理论上,像 pow(pow(30px, 3), 1/3) 这样的表达式应当能做到:内部 pow(30px, 3) 解析为值27000,类型为 «[ "length" → 3 ]»(即 <length>³),再由 pow(X, 1/3) 开立三次方根,指数乘以1/3,得到 «[ "length" → 1 ]»,匹配 <length>

在纯数学领域这肯定成立,但在计算机二进制浮点数中,幂运算有时并不能精确抵消,最终可能导致数学函数无效,原因难以跟踪。(例如JS中,计算 Math.pow(Math.pow(30, 10/3), .1+.1+.1),结果不是30,因为 .1+.1+.1 并非严格等于3/10,而 (10/3) * (.1 + .1 + .1) 实际上略大于1。)

强制作者先将值转换为数字再做运算,最后再转回想要的单位,虽然麻烦,但能避免数值精度问题:calc(pow(pow(30px / 1px, 3), 1/3) * 1px) 一定能解析成 <length>,其值即使不是精确30,也会非常接近30,即使精度损失导致幂没能完全抵消。

其次,预期冲突。有些作者希望 pow(30px, 2) 的结果是 900px(见 这个Sass issue),即只对数值平方,单位不变。但这样结果就取决于参数的单位;如果 1em16px,那么 pow(1em, 2)1em,而 pow(16px, 2)256px16em,同样参数实际得到的结果却完全不同!CSS允许值自由规范化,而且更复杂表达式如 pow(2em + 10px, 2) 也很难解释。

同样,强制作者先转数字再转回单位可以回避这些问题;pow(30, 2) 就是 900,作者可自行解释这个值。


hypot() 则不存在这些问题。单位的数值精度无需担心,输入输出类型一致。结果也不依赖单位,因为其运算本质如此;hypot(3em, 4em)hypot(48px, 64px)1em 等于 16px 时都得到相同的长度:5em80px。所以允许作者直接在 hypot() 中用带单位的值。

log(A, B?) 函数包含一个或两个 计算(分别为待取对数的值和对数的底,底默认为e),必须解析为<number>,返回A以B为底的对数,结果为 <number>,返回类型与输入 计算类型保持一致

exp(A) 函数包含一个 计算,必须解析为 <number>,返回 pow(e, A) 的值,结果为 <number>,返回类型与输入 计算类型保持一致

pow() 函数在如 CSS Modular Scale 这种策略中很有用,它让页面上所有字体大小都按固定比率相关联。

这些大小可以很容易地写成自定义属性:

:root {
  --h6: calc(1rem * pow(1.5, -1));
  --h5: calc(1rem * pow(1.5, 0));
  --h4: calc(1rem * pow(1.5, 1));
  --h3: calc(1rem * pow(1.5, 2));
  --h2: calc(1rem * pow(1.5, 3));
  --h1: calc(1rem * pow(1.5, 4));
}

...而不是直接写预先计算好的数值如 5.0625rem (即 calc(1rem * pow(1.5, 4)) 的值),这样在样式表中来源不明。

单参数时,hypot() 返回输入的绝对值;hypot(2em)hypot(-2em) 都得 2em

多参数时,它给出以这些值为边长的盒子的主对角线长度。这在与变换相关的场景很有用,比如计算元素在按某个X、Y、Z量平移时实际移动的距离。

例如,hypot(30px, 40px) 结果为 50px,这正是元素经 translate(30px, 40px) 变换后起止位置间的距离。如果作者希望元素随着距离增大而变小(比如做词云),就能用这个距离做缩放因子。

单参数时,log() 返回参数的“自然对数”(以e为底),与JavaScript一致。

如果想要以10为底(例如统计某值有几位)或以2为底(统计二进制位数),可用 log(X, 10)log(X, 2)

10.5.1. 参数取值范围

pow(A, B) 中,如果A为负且有限,B为有限,B必须是整数,否则结果为NaN。

如果A或B为无穷大或0,结果见下表:

A 是 −∞ A 是 0⁻ A 是 0⁺ A 是 +∞
B 是 −有限 若B为奇整数为0⁻,否则为0⁺ 若B为奇整数为−∞,否则为+∞ +∞ 0⁺
B 是 0 始终为1
B 是 +有限 若B为奇整数为−∞,否则为+∞ 若B为奇整数为0⁻,否则为0⁺ 0⁺ +∞
A < -1 A = -1 -1 < A < 1 A = 1 A > 1
B 是 +∞ 结果为+∞ 结果为NaN 结果为0⁺ 结果为NaN 结果为+∞
B 是 −∞ 结果为0⁺ 结果为NaN 结果为+∞ 结果为NaN 结果为0⁺

sqrt(A) 中,若A为+∞,结果为+∞。若A为0⁻,结果为0⁻。若A小于0,结果为NaN。

hypot(A, …) 中,任一输入为无穷大,结果为+∞。

log(A, B) 中,若B为1或负数,B在0到1之间或大于1都有效。结果为NaN。若A为负数,结果为NaN。若A为0⁺或0⁻,结果为−∞。若A为1,结果为0⁺。若A为+∞,结果为+∞。

exp(A) 中,若A为+∞,结果为+∞。若A为−∞,结果为0⁺。

(关于§ 10.9 类型检查,以及数学函数如何处理NaN和无穷大,详见该节。)

所有这些行为都旨在与大多数编程语言,尤其是JS中的“标准”定义一致。

唯一不同于JS同名函数的地方在于,NaN在所有函数中都是“传染性”的:只要有任意参数为NaN,函数就返回NaN。

JS 行为细节

JS中有两种情况NaN不会“传染”到数学函数:

  • Math.hypot(Infinity, NaN) 会返回 Infinity

  • Math.pow(NaN, 0) 会返回 1

逻辑似乎是,只要把NaN替换成任意数,返回值都一样。但JS的 Math 函数其实并不总这样:Math.max(Infinity, NaN) 返回 NaN,不是 InfinityMath.min(-Infinity, NaN) 也是如此。

由于这是错误边角情况,JS自身也不一致,NaN 的识别/处理通常在CSS更高层完成,而不是在底层数学函数里,所以CSS选择了更一致的方案:所有函数一律“传染”NaN。

10.6. 符号相关函数:abs()sign()

符号相关函数——abs()sign()——用于计算参数符号相关的函数。

abs(A) 函数包含一个 计算参数A,返回A的绝对值,类型与输入相同:如果A为正或0⁺,直接返回A,否则为 -1 * A

sign(A) 函数包含一个 计算参数A,A为负数时返回-1,A为正数时返回+1,A为0⁺时返回0⁺,A为0⁻时返回0⁻。返回类型为<number>,与输入 计算类型保持一致

注意: 这两个函数操作的都是参数完全化简/解析后的值,乍看可能不直观。特别是像 10% 这样的表达式,解析后可能是正也可能是负,取决于它实际被应用到什么上。例如在 background-position 属性中,如果背景图片大于背景区域,正百分比最终会变成负长度,反之亦然。因此 sign(10%) 可能返回 1-1,甚至 0(如相对于零长度)。

10.7. 数值关键词

计算中的关键词用于获取难以或无法用字面量表示的值。每个关键词都定义了其值、类型及其解析时机。

10.7.1. 数值常量:epi

虽然三角与指数函数已能实现很多复杂的数值运算,但有时仍需手动拼接一些合理的表达式,这些表达式常常包含著名常量,如 eπ

为了避免作者手动输入这些常量的多位数字,部分常量可直接使用:

e

自然对数的底数,约等于2.7182818284590452354。

pi

圆周长与直径的比值,约等于3.1415926535897932。

这两个关键词都是 <number>,在解析时确定值。

注意: 这些关键词只能在计算表达式内使用,如 calc(pow(e, pi) - pi)min(pi, 5, e)。若在计算表达式外使用,则按普通关键词处理:animation-name: pi; 指动画名为"pi";line-height: e; 是无效的(不是 line-height: 2.7,但 line-height: calc(e); 是有效的)。

10.7.2. 奇异数值常量:infinity-infinityNaN

计算或其子树变为无穷大NaN时,已无法用数值表示。为便于序列化这些奇异值,定义如下数学常量:

infinity

正无穷(+∞)

-infinity

负无穷(−∞)

NaN

值为NaN

这些关键词都是 <number>,在解析时确定值。

与CSS关键词惯例一样,这些关键词ASCII大小写不敏感因此 calc(InFiNiTy) 也是合法的。NaN 必须以此规范大小写序列化。

注意: 这些关键词是 <number>,要得到无限长度,例如需要 calc(infinity * 1px) 这样的表达式。

注意: 这些常量主要是为了让无穷大/NaN值的序列化更简单明了,但也可用来表示“最大可能值”,因为无穷大的值会被裁剪到允许范围。虽然实际这样用不多,但确有需要时,infinity 比随便写一个巨大数字意图更明确。

10.7.3. 数值变量

其它规范可定义可在特定上下文下用于计算的额外关键词。例如,relative color 语法定义了多个颜色通道关键词,表示每个通道的值为 <number>

定义此类关键词的规范必须为每个关键词定义:

10.8. 语法

数学函数的语法如下:

<calc()>  = calc( <calc-sum> )
<min()>   = min( <calc-sum># )
<max()>   = max( <calc-sum># )
<clamp()> = clamp( [ <calc-sum> | none ], <calc-sum>, [ <calc-sum> | none ] )
<round()> = round( <rounding-strategy>?, <calc-sum>, <calc-sum>? )
<mod()>   = mod( <calc-sum>, <calc-sum> )
<rem()>   = rem( <calc-sum>, <calc-sum> )
<sin()>   = sin( <calc-sum> )
<cos()>   = cos( <calc-sum> )
<tan()>   = tan( <calc-sum> )
<asin()>  = asin( <calc-sum> )
<acos()>  = acos( <calc-sum> )
<atan()>  = atan( <calc-sum> )
<atan2()> = atan2( <calc-sum>, <calc-sum> )
<pow()>   = pow( <calc-sum>, <calc-sum> )
<sqrt()>  = sqrt( <calc-sum> )
<hypot()> = hypot( <calc-sum># )
<log()>   = log( <calc-sum>, <calc-sum>? )
<exp()>   = exp( <calc-sum> )
<abs()>   = abs( <calc-sum> )
<sign()>  = sign( <calc-sum> )
<calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
<calc-product> = <calc-value> [ [ '*' | '/' ] <calc-value> ]*
<calc-value> = <number> | <dimension> | <percentage> |
               <calc-keyword> | ( <calc-sum> )
<calc-keyword> = e | pi | infinity | -infinity | NaN
<rounding-strategy> = nearest | up | down | to-zero

在某些上下文中,可以定义额外的 <calc-keyword> 值为有效值。 (例如,在 relative color 语法中,适当的通道关键字是允许的。)

此外,在 +- 运算符两侧必须有 空白。 (*/ 运算符可以不带空白使用。)

上面的一些数学函数对其 <calc-sum> 参数有额外限制。 详见各个函数的定义。

UA 必须至少支持包含 32 个 <calc-value> 项的 计算,以及至少 32 层嵌套(括号或函数)。 对于支持可变参数个数的函数(如 min()),还必须至少支持 32 个参数。 如果一个 计算 项数、参数数或嵌套层数超过支持上限,则必须视为无效。

10.9. 类型检查

数学函数可以有多种类型,比如 <length><number> 等,取决于其包含的 计算,详见下文。 它可以用在允许该类型值的任何地方。

例如,width 属性接受 <length> 值,所以一个能解析为 <length>数学函数,比如 calc(5px + 1em),可以用于 width

此外,解析为 数学函数<number> 的,可以用于只接受 <integer> 的地方;值会在解析时四舍五入为最接近的整数

运算符会形成子表达式,其类型由参数决定。

注意: 之前的规范版本对乘除法参数有限制,避免产生更复杂的中间结果(如 1px * 1em,即 <length>²),并便于在解析时检测除零。本版本已放宽这些限制。

确定计算的类型
一个值包含百分比,当其 类型为«[ "percent" → 1 ]»,或类型的百分比提示非空。
两个或多个计算具有一致类型,当相加类型不失败时。 一致类型为类型相加的结果。
使类型 baseinput 一致
  1. baseinput 都有不同的非空百分比提示,则不能使其一致,返回失败。

  2. base百分比提示为null,则设为input百分比提示

  3. 返回 base

数学函数本身有类型,由其包含的计算决定:

calc()
abs()

其包含的 计算的类型。

min()
max()
clamp()
hypot()
round()
mod()
rem()

逗号分隔 计算 的类型 相加 的结果。

asin()
acos()
atan()
atan2()

«[ "angle" → 1 ]»。

sign()
sin()
cos()
tan()
pow()
sqrt()
log()
exp()

«[ ]»(空映射)。

如果上述类型为失败,则 数学函数 无效。

数学函数 会解析为 <number><length><angle><time><frequency><resolution><flex><percentage>,取决于其类型 匹配哪个产生式。(这些类别互斥。) 如果不能 匹配任一项,则 数学函数 无效。

注意: 代数化简不影响 数学函数 或其解析类型的有效性。例如,calc(5px - 5px + 10s)calc(0 * 5px + 10s) 都是无效的,因为尝试将长度与时间相加。

注意: 注意 <percentage> 相对于 <number>(如 opacity)的情况下,是不能与数字“组合”的——opacity: calc(.25 + 25%) 是无效的。允许这样做会给“单位代数”带来很大问题(如允许对<dimension>进行乘除),而且到目前为止没有带来新功能。(比如 opacity: 25%opacity: .25 等价,仅仅是语法转换。)你仍然可以用它们做其他运算,如 opacity: calc(100% / 3); 是有效的。

注意: 因为 <number-token> 总是被解释为 <number><integer>,“无单位0” <length>数学函数中不支持。即 width: calc(0 + 5px); 是无效的,因为它尝试将 <number><length> 相加,虽然 width: 0;width: 5px; 都是有效的。

注意: 虽然有少数属性裸 <number> 在 used-value 阶段会变为 <length>(如 line-heighttab-size),<number>calc() 中永远不会变成“类长度”。它们始终是 <number>

注意: 在怪异模式 [QUIRKS] 下,一些本只接受 <length> 的属性也定义为接受 <number>,并将其解释为 px 长度。和无单位零一样,这对 数学函数 的解析和行为无影响,不过解析为 数学函数<number> 的,在怪异模式下可能变为有效(并作为 px 长度解释)。

10.9.1. 无穷大、NaN 与有符号零

数学函数遵循 IEEE-754 语义,意味着它们识别正零和负零、正无穷和负无穷,以及 NaN(非数)。

不过,这些概念只在 计算树 内保留;如果 顶层计算(即未直接嵌套于其他 数学函数中的 数学函数)会产生这些特殊值,则会“屏蔽”为标准可表示值,详见下文。

有符号零(此处记为 0⁺ 或 0⁻)不能在 CSS 中直接书写;0+0-0 都产生标准“无符号”零,规则上视为正(0⁺)。

有符号零 可通过以下方式产生:

有符号零 不会逃逸 顶层计算;会被屏蔽成“无符号”零。

无穷大 (此处记为 +∞ 或 −∞) 可通过 数学常量 infinity-infinity 直接书写,也可由一些计算产生:

注意: 下面 NaN 的产生规则,高于上述无穷大的规则。

无穷大 不会逃逸 顶层计算;会被裁剪到上下文允许的最小或最大值,详见 § 10.12 范围检查

NaN(即“非数”,not a number) 是某些无定义结果运算的结果。 可通过 数学常量 NaN 直接书写,也可由一些计算产生:

NaN 不会逃逸 顶层计算;会被屏蔽为零值。

例如,calc(-5 * 0) 会得到无符号零——计算结果是 0⁻,但作为 顶层计算,会被屏蔽为无符号零。

calc(1 / calc(-5 * 0)) 会得到 −∞,与 calc(1 / (-5 * 0)) 一样——内部 calc 得到 0⁻,作为非 顶层计算,原样传递给外层 calc 从而得 −∞。若被屏蔽为无符号零,则会得到 +∞。

10.10. 内部表示

内部表示指的是数学函数计算树:一个树结构,分支节点为运算符节点,对应于数学函数(如 Min、Cos、Sqrt 等)或计算中的运算符(Sum、Product、Negate 和 Invert,即calc-operator 节点),叶节点为数值(如数字、带单位数、百分比)或可解析为数值类型的非数学函数

数学函数根据函数类型被转换为计算树

calc()

calc() 函数的内部表示,是其参数解析为计算的结果。

其他任意数学函数

内部表示为与函数同名的运算符节点,其子节点为对每个参数解析为计算的结果,顺序与参数一致。

解析一个计算时,给定以计算values为组件值列表,返回计算树
  1. 丢弃values中的所有<whitespace-token>

  2. values中的某项为<delim-token>,且值为 "+", "-", "*", "/",则为“运算符”;否则为“值”。

  3. 收集子节点到 Product 和 Invert 节点中。

    对于values中连续由"*"或"/"分隔的值项:

    1. 将每个 "/" 运算符右侧的值项 rhs 替换为以 rhs 为子节点的 Invert 节点。

    2. 将整个序列替换为以这些值项为子节点的 Product 节点。

  4. 收集子节点到 Sum 和 Negate 节点中。

    1. 将每个 "-" 运算符右侧的值项 rhs 替换为以 rhs 为子节点的 Negate 节点。

    2. 如果values只剩一个项,且为 Product 节点或括号包裹的simple block,用该项替换values

      否则,用以values值项为子节点的 Sum 节点替换values

  5. 此时 values 是 Sum、Product、Negate、Invert 节点组成的树,叶节点为其它类型的值。处理叶节点:

    values中每个叶节点 leaf

    1. leaf 为括号包裹的simple block,用解析其内容后的结果替换该叶节点。

    2. leaf数学函数,用该函数的内部表示替换该叶节点。

  6. 返回简化计算树的结果。

10.10.1. 简化

内部表示会对数学函数尽可能进行即时简化,采用标准代数化简(如乘法分配、同单位合并等)。

用于非属性上下文(如@font-face描述符)时,数学函数指定值方式简化。

简化计算树 root
  1. root 为数值:

    1. 如为待解析的百分比且有足够信息,解析为实际数值,并用对应规范单位表达,返回该值。

    2. 如为非规范单位的带单位数,且有足够信息可转为规范单位,转换并返回。

    3. 如为可解析的<calc-keyword>,返回其解析结果并简化

    4. 否则,返回 root

  2. root 为其它叶节点(非运算符节点):

    1. 如有足够信息确定其数值,返回其值,并用规范单位表达。

    2. 否则,返回 root

  3. 此时 root运算符节点简化其所有计算子节点。

  4. root 为非calc-operator 节点运算符节点,且所有子节点均为数值,且有足够信息计算该运算,则返回运算结果,并用规范单位表达。

    此时若仍有百分比,通常会阻止该节点进一步简化,因为还需其他值解析百分比(否则前面已经被转为具体值)。比如 "min" 操作,因为百分比可能基准为负,比较关系可能变化。

    但“原始”百分比(如opacity属性)不需解析基准时,可能不会阻止简化。

  5. root 为 Min 或 Max 节点,尝试部分简化:

    1. 遍历root的所有子节点 child

      child 为可比较大小的数值,且有其它同单位的数值子节点,则将所有同单位子节点合并为一个值,替换 child,移除其它相关子节点。

    2. root 只剩一个子节点,返回该子节点,否则返回 root

  6. root 为 Negate 节点:

    1. 如其子节点为数值,返回一个相等数值但取反(0 - value)。

    2. 如其子节点为 Negate 节点,返回子节点的子节点。

    3. 返回 root

  7. root 为 Invert 节点:

    1. 如其子节点为数字(非百分比/维度),返回其倒数。

    2. 如其子节点为 Invert 节点,返回子节点的子节点。

    3. 返回 root

  8. root 为 Sum 节点:

    1. 将子节点为 Sum 节点的,替换为其子节点。

    2. 对同单位数值子节点,合并为一个数值节点,单位相同。

      (如合并纯数字、百分比、px值等)

    3. 如只剩一个子节点,返回该节点,否则返回 root

    注意: 零值项不能直接从 Sum 移除,只能与同单位值合并。(因为即便为零,单位有时会影响行为。)

  9. root 为 Product 节点:

    1. 将子节点为 Product 节点的,替换为其子节点。

    2. 如有多个数字子节点(非百分比/维度),合并为一个数字。

    3. 如仅有两个子节点,一个为数字,一个为所有子节点为数值的 Sum,给 Sum 的每个子节点乘以该数字,返回 Sum。

    4. 如仅含数值与/或 Invert 节点,且所有类型相乘后匹配某种数学函数类型,则将所有子节点数值相乘(Invert 节点为倒数),返回结果并用规范单位表达。

    5. 返回 root

10.11. 计算值

计算值数学函数计算树,在计算值时利用所有可用信息简化后的结果。(如 empx 比例,某些属性下百分比的解析方式等。)

若百分比在计算值阶段未解析,则在数学函数中同样不解析。例如 calc(100% - 100% + 1px) 结果为 calc(0% + 1px),而不是 1px。如某些属性对百分比有特殊计算规则(如height),则只要含百分比的数学函数都适用该规则。

计算树会在使用值阶段再次简化;利用使用值时的信息,数学函数最终总能简化为单一数值。

例如,font-size 的百分比在计算值阶段就会解析,以便计算字体相关长度单位,而background-position的百分比则依赖布局,直到使用值阶段才解析。

因此,background-position 的计算会在 calc() 中保留百分比,而 font-size 会直接算成长度。

鉴于表格单元格和表格元素宽高计算的复杂性,同时混合百分比和非零长度用于表格列、列组、行、行组、单元格宽高的数学表达式(无论自动还是固定布局表),必须视为指定了 auto

10.12. 范围检查

数学函数中不会进行解析时的范围检查,因此超出范围的值不会导致声明无效。但顶层计算的结果必须被裁剪到目标上下文允许的范围。裁剪会在计算值阶段尽可能进行,如无法完全简化以检查范围,则在使用值阶段裁剪。(裁剪不会在指定值阶段进行。)

注意: 所有接受 calc() 的上下文都必须定义为闭区间(不是开区间)。

注意: 定义上,±∞ 总在任何属性允许范围之外,会裁剪为最小值或最大值。即使某些属性语法允许用关键字表达无穷大(如 animation-iteration-count),最终也会裁剪 ±∞,因为数学函数不能解析为关键字;属性的数值部分总有最小/最大值。

另外,如数学函数解析为<number>,而用于只接受<integer>的地方,则计算值使用值同样四舍五入为最接近整数,如同上面的裁剪。

由于宽度不能小于 0px,以下三种声明等价:
width: calc(5px - 10px);
width: calc(-5px);
width: 0px;

但注意 width: -5px 不等价于 width: calc(-5px)! 超出范围的值在 calc() 外是语法无效的,会导致整个声明被丢弃。

10.13. 序列化

本节仍在讨论中

序列化一个数学函数 fn
  1. 如果fn对应的计算树的根节点是数值(数字、百分比或带单位数),且当前要序列化的是计算值或更晚阶段,则将其裁剪到上下文允许的范围(如有必要),按正常方式序列化该值并返回。

  2. 如果fn表示无穷或NaN值:

    1. s字符串 "calc("。

    2. fn的值对应的关键词 infinity-infinityNaN 序列化,并追加到s后。

    3. 如果fn类型不是«[ ]»(即非纯 <number>),则在s后追加" * "。用fn规范单位(如 px 对应<length>)创建一个数值1,序列化该数值并追加到s后。

    4. 返回s

  3. 如果计算树的根节点是数值或calc-operator 节点,令s为字符串 "calc("。否则,令s为根节点名称的小写(如 "sin" 或 "max"),再加一个左括号"("。

  4. 对根节点的每个子节点,序列化计算树。如结果以 "(" 开头且以 ")" 结尾,去掉这两个字符。将所有结果用", "(逗号加空格)拼接,再追加到s

  5. s后追加")"(右括号)。

  6. 返回s

序列化计算树
  1. root计算树的根节点。

  2. 如果root是数值或非数学函数,按其常规规则序列化并返回结果。

  3. 如果root不是 Sum、Negate、Product 或 Invert 节点,则为对应函数序列化数学函数,其子节点作为函数逗号分隔的计算参数,并返回结果。

  4. root为 Negate 节点,令s为字符串 "(-1 * "。序列化其子节点并追加到s。追加")"并返回。

  5. root为 Invert 节点,令s为字符串 "(1 / "。序列化其子节点并追加到s。追加")"并返回。

  6. root为 Sum 节点,令s为字符串 "("。排序 root 的子节点序列化第一个子节点并追加到s遍历其余子节点:

    1. child为 Negate 节点,追加" - "到s,再序列化Negate的子节点并追加到s

    2. child为负数,追加" - "到s,再序列化其相反数并追加。

    3. 否则,追加" + "到s,再序列化child并追加。

    最后追加")"并返回。

  7. root为 Product 节点,令s为字符串 "("。排序 root 的子节点序列化第一个子节点并追加到s遍历其余子节点:

    1. child为 Invert 节点,追加" / "到s,再序列化Invert的子节点并追加。

    2. 否则,追加" * "到s,再序列化child并追加。

    最后追加")"并返回。

排序计算的子节点 nodes
  1. ret为一个空列表。

  2. nodes包含数字,将其移出并加入ret

  3. nodes包含百分比,将其移出并加入ret

  4. nodes包含带单位数,将它们移出,按单位ASCII不区分大小写排序,追加到ret

  5. nodes还有其他项,按原顺序追加到ret

  6. 返回ret

例如,calc(20px + 30px) 作为指定值序列化为 calc(50px),作为计算值序列化为 50px

类似 calc(20px + 0%) 会序列化为 calc(0% + 20px),保留两个项(保留零值项很重要,这样 calc() 在过渡过程中某值临时为零时不会突然“变形”,也不必在全为零时“选一个单位”)。

calc(20px + 2em) 这样的值,指定值序列化为 calc(2em + 20px)(两个单位在指定值阶段不兼容,按字母排序),计算值如 52pxem 在计算值阶段转为绝对长度,假设 1em = 16px,则合并为 52px,此时会去掉 calc() 包裹)。

用于非属性上下文(如@font-face描述符)时,数学函数指定值方式简化。

更多序列化信息见[CSSOM]

10.14. 数学函数的组合

插值数学函数,无论彼此之间还是与数值/其他数值函数之间,定义为 Vresult = calc((1 - p) * VA + p * VB)。(简化后表达式可能进一步缩减。)

加法数学函数,无论彼此之间还是与数值/其他数值函数之间,定义为 Vresult = calc(VA + VB)。(简化后表达式可能进一步缩减。)

附录A:协调型列表属性

某些列表属性具有协调效果:它们的值列表中每一项对应一个独立的效果,各属性列表的相同序号项指向同一个效果。通常这些协调值也可以一起指定为列表型简写属性的单个条目。

典型例子是列表型background-*属性,可以指定多层背景图片。每个用于控制图片尺寸、平铺、定位等的属性,其值列表第N项描述作用于第N个背景图片的效果。

协调型列表属性组会创建一个协调值列表,每一项包含该组内各属性的一个值,这些值共同定义一个效果,如一层背景或一个动画。协调值列表按如下方式组装:

附录B:IANA相关事项

about:invalid URL 方案注册

本节定义并注册 about:invalid URL,符合[RFC6694]定义的注册流程。

官方注册记录见 http://www.iana.org/assignments/about-uri-tokens/about-uri-tokens.xhtml

注册Token invalid
预期用途 about:invalid URL 用于指向不存在的文档和通用错误条件。当需要URL但默认值不应能被解析为任何类型文档时,可用此URL。
联系方式/变更控制 CSS WG <www-style@w3.org>(代表W3C)
规范 CSS Values and Units Module Level 3

附录C:怪异长度(Quirky Lengths)

当CSS在怪异模式下被解析时,<quirky-length> 是一种 <length> 类型,仅在以下特定属性中有效:

在包含或引用这些属性的属性中有效,比如 background 简写属性,或出现在如 函数式表示法(如 calc())中,除了在 rect() 作为 clip 属性时必须允许。

另外,<quirky-length><length> 作为受影响属性被 @supports 规则解析时必须有效,但在 CSS.supports() 方法中用于这些属性时有效。

<quirky-length> 在语法上与 <number-token> 完全相同,且会被解释为值相同的 px 长度。

(换句话说,怪异模式允许受影响属性中的所有 px 长度可以不加单位直接书写,类似于无单位的0长度。)

致谢

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

其次,我们要感谢 Anthony Frehner、Emilio Cobos Álvarez、Koji Ishii、Noam Rosenthal 和 Xidorn Quan 的意见和建议,这些都改进了第4级规范。

变更记录

近期变更

(本节为自第3级以来的增补的子集。)

2023年12月18日 WD以来的重大变更:

2023年10月27日 WD以来的重大变更:

2023年4月6日 WD以来的重大变更:

2022年10月19日 WD以来的重大变更:

2021年12月16日 WD以来的重大变更:

2021年10月16日 WD以来的变更:

2021年9月30日 WD以来的变更:

2021年7月15日 WD以来的变更:

2020年11月11日 WD以来的变更:

自第3级以来的增补

CSS Values and Units Level 3以来变更:

CSS Values and Units Level 3以来的增补:

安全性注意事项

本规范未引入新的安全性注意事项。

本规范定义了 url()src() 函数(<url>),允许CSS发起网络请求。根据它们所用于的特性,这些请求可能暴露用户是否能访问某网络资源,并暴露内容信息(如样式表规则、图片尺寸、字体度量等),还可能通过URL泄露数据。

隐私注意事项

本规范定义了可暴露用户屏幕尺寸的单位(视口百分比长度)、默认字体大小,以及可能暴露部分可用字体信息(字体相关长度)。

本规范定义了 url()src() 函数(<url>),允许CSS发起网络请求。根据其所用特性,这些请求可能暴露用户是否能访问某网络资源,并暴露内容信息(如样式表规则、图片尺寸、字体度量等),也可能通过URL泄露数据。

一致性

文档约定

一致性要求通过描述性断言和 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 特性冲突,CSSWG 推荐遵循最佳实践实现 不稳定特性和 专有扩展

非实验性实现

一旦规范进入候选推荐(CR)阶段,就可以进行非实验性实现。实现者应当在能够证明已按规范正确实现 CR 级特性时,发布无前缀的实现。

为建立和保持 CSS 在各实现间的互操作性,CSS 工作组请求非实验性 CSS 渲染器在发布任何 CSS 特性的无前缀实现前,向 W3C 提交实现报告(如有必要,还需提交用于该报告的测试用例)。提交给 W3C 的测试用例由 CSS 工作组审核和修正。

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

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-2023]
Chris Lilley 等. CSS Snapshot 2023。2023年12月7日。NOTE。URL:https://www.w3.org/TR/css-2023/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4。2022年11月3日。WD。URL:https://www.w3.org/TR/css-box-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-COLOR-4]
Tab Atkins Jr.;Chris Lilley;Lea Verou. CSS Color Module Level 4。2022年11月1日。CR。URL:https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley 等. CSS Color Module Level 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-COUNTER-STYLES-3]
Tab Atkins Jr.. CSS Counter Styles Level 3。2021年7月27日。CR。URL:https://www.w3.org/TR/css-counter-styles-3/
[CSS-DISPLAY-3]
Elika Etemad;Tab Atkins Jr.. CSS Display Module Level 3。2023年3月30日。CR。URL:https://www.w3.org/TR/css-display-3/
[CSS-EASING-1]
Brian Birtles;Dean Jackson;Matt Rakow. CSS Easing Functions Level 1。2023年2月13日。CR。URL:https://www.w3.org/TR/css-easing-1/
[CSS-FONTS-4]
Chris Lilley. CSS Fonts Module Level 4。2024年2月1日。WD。URL:https://www.w3.org/TR/css-fonts-4/
[CSS-FONTS-5]
Chris Lilley. CSS Fonts Module Level 5。2024年2月6日。WD。URL:https://www.w3.org/TR/css-fonts-5/
[CSS-GRID-2]
Tab Atkins Jr.;Elika Etemad;Rossen Atanassov. CSS Grid Layout Module Level 2。2020年12月18日。CR。URL:https://www.w3.org/TR/css-grid-2/
[CSS-IMAGES-4]
Tab Atkins Jr.;Elika Etemad;Lea Verou. CSS Images Module Level 4。2023年2月17日。WD。URL:https://www.w3.org/TR/css-images-4/
[CSS-INLINE-3]
Dave Cramer;Elika Etemad. CSS Inline Layout Module Level 3。2023年4月1日。WD。URL:https://www.w3.org/TR/css-inline-3/
[CSS-MASKING-1]
Dirk Schulze;Brian Birtles;Tab Atkins Jr.. CSS Masking Module Level 1。2021年8月5日。CR。URL:https://www.w3.org/TR/css-masking-1/
[CSS-OVERFLOW-3]
Elika Etemad;Florian Rivoal. CSS Overflow Module Level 3。2023年3月29日。WD。URL:https://www.w3.org/TR/css-overflow-3/
[CSS-PAGE-3]
Elika Etemad. CSS Paged Media Module Level 3。2023年9月14日。WD。URL:https://www.w3.org/TR/css-page-3/
[CSS-POSITION-3]
Elika Etemad;Tab Atkins Jr.. CSS Positioned Layout Module Level 3。2023年4月3日。WD。URL:https://www.w3.org/TR/css-position-3/
[CSS-SCOPING-1]
Tab Atkins Jr.;Elika Etemad. CSS Scoping Module Level 1。2014年4月3日。WD。URL:https://www.w3.org/TR/css-scoping-1/
[CSS-SHAPES-1]
Rossen Atanassov;Alan Stearns. CSS Shapes Module Level 1。2022年11月15日。CR。URL:https://www.w3.org/TR/css-shapes-1/
[CSS-SIZING-3]
Tab Atkins Jr.;Elika Etemad. CSS Box Sizing Module Level 3。2021年12月17日。WD。URL:https://www.w3.org/TR/css-sizing-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.;Simon Sapin. CSS Syntax Module Level 3。2021年12月24日。CR。URL:https://www.w3.org/TR/css-syntax-3/
[CSS-TEXT-4]
Elika Etemad 等. CSS Text Module Level 4。2023年10月20日。WD。URL:https://www.w3.org/TR/css-text-4/
[CSS-TYPED-OM-1]
Shane Stephens;Tab Atkins Jr.;Naina Raisinghani. CSS Typed OM Level 1。2018年4月10日。WD。URL:https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-5]
CSS Values and Units Module Level 5。编辑草案。URL:https://drafts.csswg.org/css-values-5/
[CSS-VARIABLES-1]
Tab Atkins Jr.. CSS Custom Properties for Cascading Variables Module Level 1。2022年6月16日。CR。URL:https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
Elika Etemad;Koji Ishii. CSS Writing Modes Level 4。2019年7月30日。CR。URL:https://www.w3.org/TR/css-writing-modes-4/
[CSS2]
Bert Bos 等. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification。2011年6月7日。REC。URL:https://www.w3.org/TR/CSS21/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification。2016年4月12日。WD。URL:https://www.w3.org/TR/CSS22/
[CSS3-BACKGROUND]
Elika Etemad;Brad Kemper. CSS Backgrounds and Borders Module Level 3。2023年12月19日。CR。URL:https://www.w3.org/TR/css-backgrounds-3/
[CSS3-FONTS]
John Daggett;Myles Maxfield;Chris Lilley. CSS Fonts Module Level 3。2018年9月20日。REC。URL:https://www.w3.org/TR/css-fonts-3/
[CSS3-IMAGES]
Tab Atkins Jr.;Elika Etemad;Lea Verou. CSS Images Module Level 3。2023年12月18日。CR。URL:https://www.w3.org/TR/css-images-3/
[CSSOM]
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/
[FETCH]
Anne van Kesteren. Fetch 标准。现行标准。URL:https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren 等. HTML 标准。现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola. Infra 标准。现行标准。URL:https://infra.spec.whatwg.org/
[MEDIAQUERIES-5]
Dean Jackson 等. Media Queries Level 5。2021年12月18日。WD。URL:https://www.w3.org/TR/mediaqueries-5/
[RFC2119]
S. Bradner. 用于RFC中的需求程度关键词。1997年3月。最佳当前实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[UNICODE]
Unicode 标准。URL:https://www.unicode.org/versions/latest/
[URL]
Anne van Kesteren. URL 标准。现行标准。URL:https://url.spec.whatwg.org/
[WEB-ANIMATIONS-1]
Brian Birtles 等. Web Animations。2023年6月5日。WD。URL:https://www.w3.org/TR/web-animations-1/

参考性引用

[CSS-ANIMATIONS-1]
David Baron 等. CSS Animations Level 1。2023年3月2日。WD。URL:https://www.w3.org/TR/css-animations-1/
[CSS-BREAK-3]
Rossen Atanassov;Elika Etemad. CSS Fragmentation Module Level 3。2018年12月4日。CR。URL:https://www.w3.org/TR/css-break-3/
[CSS-CASCADE-3]
Elika Etemad;Tab Atkins Jr.. CSS 级联与继承 第3级。2021年2月11日。REC。URL:https://www.w3.org/TR/css-cascade-3/
[CSS-COLOR-3]
Tantek Çelik;Chris Lilley;David Baron. CSS Color Module Level 3。2022年1月18日。REC。URL:https://www.w3.org/TR/css-color-3/
[CSS-GRID-1]
Tab Atkins Jr. 等. CSS Grid Layout Module Level 1。2020年12月18日。CR。URL:https://www.w3.org/TR/css-grid-1/
[CSS-OVERFLOW-4]
David Baron;Florian Rivoal;Elika Etemad. CSS Overflow Module Level 4。2023年3月21日。WD。URL:https://www.w3.org/TR/css-overflow-4/
[CSS-RHYTHM-1]
Koji Ishii;Elika Etemad. CSS Rhythmic Sizing。2017年3月2日。WD。URL:https://www.w3.org/TR/css-rhythm-1/
[CSS-TEXT-3]
Elika Etemad;Koji Ishii;Florian Rivoal. CSS Text Module Level 3。2023年9月3日。CR。URL:https://www.w3.org/TR/css-text-3/
[CSS-TEXT-DECOR-4]
Elika Etemad;Koji Ishii. CSS Text Decoration Module Level 4。2022年5月4日。WD。URL:https://www.w3.org/TR/css-text-decor-4/
[CSS-TRANSFORMS-1]
Simon Fraser 等. CSS Transforms Module Level 1。2019年2月14日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[CSS-UI-4]
Florian Rivoal. CSS 基础用户界面模块 第4级。2021年3月16日。WD。URL:https://www.w3.org/TR/css-ui-4/
[MEDIAQ]
Florian Rivoal;Tab Atkins Jr.. Media Queries Level 4。2021年12月25日。CR。URL:https://www.w3.org/TR/mediaqueries-4/
[QUIRKS]
Simon Pieters. Quirks Mode Standard。现行标准。URL:https://quirks.spec.whatwg.org/
[RFC6694]
S. Moonesamy, Ed.. The "about" URI Scheme。2012年8月。Informational。URL:https://www.rfc-editor.org/rfc/rfc6694

问题索引

可以参考 find a potential indicated element,但那是专为 Document 定义的,不适用于 ShadowRoot
CSSOM 需要指定舍入方式,且让 CSS 函数默认采用相同的舍入方式可能更好。应采用什么行为?[Issue #5689]
本节仍在讨论中
CanIUse

Support:Android Browser2.1+Baidu Browser13.18+Blackberry Browser7+Chrome4+Chrome for Android122+Edge12+Firefox3.6+Firefox for Android123+IE11+IE Mobile10+KaiOS Browser2.5+Opera11.6+Opera MiniAllOpera Mobile12+QQ Browser13.1+Safari5+Safari on iOS6.0+Samsung Internet4+UC Browser for Android15.5+

Source: caniuse.com as of 2024-03-07

CanIUse

Support:Android Browser4.4+Baidu Browser13.18+Blackberry Browser10+Chrome27+Chrome for Android122+Edge12+Firefox2+Firefox for Android123+IE (limited)9+IE Mobile10+KaiOS Browser2.5+Opera15+Opera MiniNoneOpera Mobile73+QQ Browser13.1+Safari7+Safari on iOS7.0+Samsung Internet4+UC Browser for Android15.5+

Source: caniuse.com as of 2024-03-07

CanIUse

Support:Android Browser4.4+Baidu Browser13.18+Blackberry Browser10+Chrome26+Chrome for Android122+Edge16+Firefox19+Firefox for Android123+IE (limited)9+IE Mobile (limited)10+KaiOS Browser2.5+Opera15+Opera MiniNoneOpera Mobile73+QQ Browser13.1+Safari6.1+Safari on iOS8+Samsung Internet4+UC Browser for Android15.5+

Source: caniuse.com as of 2024-03-07

CanIUse

Support:Android Browser122+Baidu Browser13.18+Blackberry Browser10+Chrome26+Chrome for Android122+Edge12+Firefox16+Firefox for Android123+IE (limited)9+IE Mobile10+KaiOS Browser2.5+Opera15+Opera MiniNoneOpera Mobile73+QQ Browser13.1+Safari6.1+Safari on iOS7.0+Samsung Internet4+UC Browser for Android15.5+

Source: caniuse.com as of 2024-03-07