CSS 语法模块第 3 级

W3C 候选推荐标准草案,

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2026/CRD-css-syntax-3-20261001/
最新发布版本:
https://www.w3.org/TR/css-syntax-3/
编辑者草案:
https://drafts.csswg.org/css-syntax/
先前版本:
历史:
https://www.w3.org/standards/history/css-syntax-3/
实现报告:
https://wpt.fyi/results/css/css-syntax?label=experimental&label=master&aligned
反馈:
CSSWG 问题仓库
编辑者:
Tab Atkins Jr. (Google)
Simon Sapin (Mozilla)
为此规范建议编辑:
GitHub 编辑器
测试套件:
https://wpt.fyi/results/css/css-syntax/

摘要

本模块从总体上描述 CSS 样式表的基本结构和语法。它定义了 CSS 的详细语法和解析方式——即如何将字节流转换为有意义的样式表。

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

本文档的状态

本节描述本文档发布时的状态。 当前 W3C 出版物列表 以及本技术报告的最新修订版 可在 W3C 标准和草案索引。中找到

本文档由 CSS 工作组 作为候选推荐标准草案,采用推荐标准 流程发布。 作为候选推荐标准发布 并不意味着获得 W3C 及其成员的认可。 候选推荐标准草案 整合了自上一份候选推荐标准以来的更改, 工作组打算将这些更改纳入后续的候选推荐标准快照。

这是一份草案文档 并且可能随时由其他文档更新、替代 或废止。 除作为正在进行的工作外,不宜引用本文档。

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

本文档受 2025 年 8 月 18 日 W3C 流程 文档管辖。

本文档由一个依据 W3C 专利政策运作的工作组制定。 W3C 维护一份 所有专利披露的公开列表 这些披露与该工作组的交付成果相关; 该页面还包含披露专利的说明。 若个人实际知晓某项其认为 包含必要权利要求的专利, 则必须按照 W3C 专利政策第 6 节 披露该信息。

1. 引言

本节不是规范性的。

本模块定义 CSS 样式表的抽象语法和解析 以及其他使用 CSS 语法的内容 (例如 HTML style 属性)。

它定义了用于将 Unicode 代码点流 (换言之,即文本) 转换为 CSS 标记流的算法, 然后进一步转换为 CSS 对象, 例如样式表、规则和声明。

1.1. 模块交互

本模块定义 CSS 样式表的语法和解析。 它取代 CSS 2.1 中定义的词法扫描器和语法。

2. CSS 语法说明

本节不是规范性的。

CSS 文档是一系列样式 规则——它们是将样式应用于文档中元素的限定规则——以及 at-rule——它们为 CSS 文档定义特殊处理 规则或值。

限定规则以 前奏开始 然后具有一个由 {} 包裹、包含一系列声明的块。 前奏的含义会根据规则出现的上下文而变化——对于样式规则,它是一个选择器,用于指定 声明将应用于哪些元素。 每个声明都有一个名称, 后跟冒号和声明值。 声明之间以分号分隔。

典型的规则可能如下所示:

p > a {
  color: blue;
  text-decoration: underline;
}

在上述规则中,"p > a" 是选择器, 如果源文档是 HTML, 它会选择所有 a 元素,这些元素是 p 元素的子元素。

"color: blue" 是一个声明,它指定 对于匹配该选择器的元素, 它们的 color 属性应具有值 blue。 类似地,它们的 text-decoration 属性应具有值 underline。

At-rule 各不相同,但它们具有 共同的基本结构。 它们以 "@" 代码点开始,后跟作为 CSS 关键字的名称。 某些 at-rule 是简单语句, 名称后跟更多 CSS 值以指定其行为, 最后以分号结束。 另一些则是块; 它们可以在名称后跟 CSS 值, 但以一个由 {} 包裹的块结束, 类似于限定规则。 甚至这些块的内容也由给定的 at-rule 决定: 有时它们包含一系列声明,就像限定 规则; 其他时候,它们可能包含其他块、at-rule,或完全不同的其他结构。

下面是几个 at-rule 示例, 用于展示它们可能包含的各种语法。

@import "my-styles.css";

@import at-rule 是一个简单语句。 在其名称之后,它接受单个字符串或 url() 函数 以指示它应导入的样式表。

@page :left {
  margin-left: 4cm;
  margin-right: 3cm;
}

@page at-rule 由可选的页面选择器(:left 伪类)组成, 后跟一个属性块,这些属性会在打印时应用于页面。 因此,它与普通样式规则非常相似, 不同之处在于其属性不应用于任何“元素”, 而是应用于页面本身。

@media print {
  body { font-size: 10pt }
}

@media at-rule 以媒体类型开始 并后跟一个可选媒体查询列表。 其块包含完整的规则, 这些规则仅在 @media 的 条件满足时应用。

属性名称和 at-rule 名称始终是 ident 序列, 它们必须以 ident-start 代码点、两个连字符, 或一个连字符后跟 ident-start 代码点开始, 然后可以包含零个或多个 ident 代码点。 你可以包含任意 代码点, 即使是 CSS 在其语法中使用的代码点, 只要对其进行转义即可。

选择器的语法在选择器规范中定义。 类似地,各种 CSS 值的语法在值与单位规范中定义。 各个 at-rule 的特殊语法可在定义它们的规范中找到。

2.1. 转义

本节不是规范性的。

任何 Unicode 代码点都可以包含在 ident 序列或带引号的字符串中 方法是对其进行转义。 CSS 转义序列以反斜杠 (\) 开始,并继续为:

2.2. 错误处理

本节不是规范性的。

当 CSS 中发生错误时, 解析器会尝试平稳恢复, 仅丢弃最少量的内容, 然后恢复正常解析。 这是因为错误并不总是错误操作——新语法对于旧解析器而言看起来像错误, 而能够向语言添加新语法 而不必担心包含它的样式表在旧 UA 中完全失效是很有用的。

精确的错误恢复行为在解析器本身中有详细说明, 但它足够简单,因此简短描述也相当准确。

解析每个构造(声明、样式规则、at-rule)之后, 用户代理会根据其预期语法对其进行检查。 如果它不匹配该语法, 则它是无效的, 并会被 UA 忽略, UA 会将其视为完全不存在。

3. CSS 的标记化和解析

用户代理必须使用本规范中描述的解析规则 从 text/css 资源生成 [CSSOM] 树。 这些规则共同定义了所谓的 CSS 解析器。

本规范定义 CSS 文档的解析规则, 无论它们在语法上是否正确。 解析算法中的某些位置被称为解析错误。 解析错误的错误处理有明确的定义: 用户代理在遇到此类问题时必须按照下文描述采取行动, 或者必须在遇到其不希望应用下述 规则的第一个错误时中止处理。

如果文档中存在一个或多个解析错误条件, 一致性检查器必须向用户报告至少一个解析错误条件, 并且如果文档中不存在解析错误条件, 则不得报告解析错误条件。 如果存在多个解析错误条件,一致性检查器可以报告多个解析错误条件。 一致性检查器不要求从解析错误中恢复, 但如果进行恢复, 则必须以与用户代理相同的方式恢复。

测试

3.1. 解析模型概述

CSS 解析过程的输入由 Unicode 代码点流组成, 它先经过标记化阶段,然后经过树构建阶段。 输出是一个 CSSStyleSheet 对象。

注:不支持脚本的实现 不必实际创建 CSSOM CSSStyleSheet 对象, 但在这种情况下,CSSOM 树仍会被用作规范其余部分的模型。

3.2. 输入字节流

解析样式表时, 构成标记化阶段输入的 Unicode 代码点流 最初可能被用户代理视为字节流 (通常来自网络或本地文件系统)。 如果是这样,用户代理必须根据特定的字符编码 将这些字节解码为 代码点。

要将 stylesheet 的字节流解码为代码 点流:
  1. 确定回退编码 stylesheet 的, 并令 fallback 为结果。

  2. 使用回退编码 fallback 解码 stylesheet 的字节流, 并返回结果。

注:解码算法 优先采用字节顺序标记(BOM), 只有在未找到 BOM 时才使用回退编码。

要确定 回退编码一个 stylesheet 的:
  1. 如果 HTTP 或等效协议为 stylesheet 提供了编码标签(例如通过 Content-Type 标头的 charset 参数), 则从 encoding label 获取编码。 如果该操作未返回失败, 则返回它。
  2. 否则,检查 stylesheet 的字节流。 如果该流的前 1024 个字节以如下十六进制序列开头:
    40 63 68 61 72 73 65 74 20 22 XX* 22 3B

    其中每个 XX 字节都是介于 016 和 2116(含)之间的值 或介于 2316 和 7F16(含)之间的值, 则获取编码 从由 XX 字节序列组成的字符串, 并将其解释为 ASCII。

    该字节序列是什么意思?

    上述字节序列 按 ASCII 解码时, 是字符串 "@charset "…";", 其中 "…" 是与编码标签相对应的字节序列。

    如果返回值为 utf-16be 或 utf-16le, 则返回 utf-8; 如果它不是失败的其他任何值, 则返回它。

    为什么声明为 utf-16 时使用 utf-8?

    编码声明的字节在 ASCII 中拼写为“@charset "…";”, 但 UTF-16 与 ASCII 不兼容。 要么你输入了完全乱码的内容(例如 䁣桡牳整•utf-16be∻)以获得文档中 正确的字节, 而我们不希望鼓励这种做法, 要么你的文档实际上采用与 ASCII 兼容的编码, 而你的编码声明是在撒谎。

    无论哪种情况,默认使用 UTF-8 都是一个合理的答案。

    此外,这也模仿了 HTML 的 <meta charset> 属性的行为。

    注:请注意,编码 声明的语法看起来像一个名为 at-rule 的 @charset, 但实际上并不存在这样的规则, 而且其书写规则比通常用于 识别这种规则的规则严格得多。 你可以在 CSS 中执行的许多操作,如果确实存在这样的规则,会产生有效的 @charset 规则, 例如使用多个空格、注释或单引号, 都会导致编码声明无法被识别。 此行为使编码声明尽可能简单, 从而最大程度提高其被正确实现的可能性。

  3. 否则,如果引用 文档提供了环境编码, 则返回它。
  4. 否则,返回 utf-8。

尽管 UTF-8 是 Web 的默认编码, 并且许多较新的基于 Web 的文件格式假定或要求使用 UTF-8 编码, 但 CSS 创建于尚不清楚哪种编码最终会占据主导地位的时期, 因此不能自动假定样式表采用 UTF-8。

样式表作者应该使用 UTF-8 编写其样式表, 并确保 HTTP 标头(或等效方法)声明样式表的编码 为 UTF-8, 或者引用文档声明其编码为 UTF-8。 (在 HTML 中,这通过向 head 添加 <meta charset=utf-8> 元素 来完成。)

如果这些选项均不可用, 作者应以 UTF-8 BOM 开始样式表 或以下确切字符

@charset "utf-8";

引用从字节解码的 CSS 样式表的文档语言 可以为每个此类样式表定义环境 编码, 当其他编码提示不可用或无法使用时,将其用作回退编码。

环境编码这一概念仅为与旧版 内容兼容而存在。 新格式和新的链接机制不应该提供环境编码, 这样在缺少更明确的信息时,样式表就会改为默认使用 UTF-8。

注:[HTML] 定义了<link rel=stylesheet> 的环境编码。

注:[CSSOM] 定义了<xml-stylesheet?> 的 环境编码。

注:[CSS-CASCADE-3] 定义 @import 的环境编码。

3.3. 预处理输入流

输入流由 随输入字节流被解码而推入其中的经过筛选的 代码点 组成。

要从一个(未经筛选的)代码点流 input 中筛选代码 点:
测试

4. 标记化

要将代码点流 input 标记化为 CSS 标记流, 重复从 input 中消费一个标记 直到遇到 <EOF-token>, 将每个返回的标记推入一个流中。

注:每次调用消费一个标记算法 都会返回单个标记, 因此它也可以“按需”用于标记化代码点流, 即在解析期间, 如果需要的话。

标记化步骤的输出是由以下零个或多个标记组成的流: <ident-token>、 <function-token>、 <at-keyword-token>、 <hash-token>、 <string-token>、 <bad-string-token>、 <url-token>、 <bad-url-token>、 <delim-token>、 <number-token>、 <percentage-token>、 <dimension-token>、 <unicode-range-token>、 <whitespace-token>、 <CDO-token>、 <CDC-token>、 <colon-token>、 <semicolon-token>、 <comma-token>、 <[-token>、 <]-token>、 <(-token>、 <)-token>、 <{-token>, 以及 <}-token>。

注:hash 标记的类型标志用于 选择器语法 [SELECT]。 只有类型为 "id" 的 hash 标记才是有效的 ID 选择器。

4.1. 标记铁路图

本节是非规范性的。

本节以铁路图的形式 提供标记器的信息性视图。 铁路图比显式解析器更紧凑, 但通常比正则表达式更易阅读。

这些图是信息性的且不完整的; 它们描述“正确”标记的语法, 但完全不描述错误处理。 提供这些图只是为了更容易直观掌握每种标记的语法。

名称类似 <foo-token> 的图表示标记。 其余图表示其他图所引用的产生式。

注释
/* 除后跟 / 的 * 之外的任何内容 */
换行符
\n \r\n \r \f
空白
空格 \t 换行符
十六进制数字
0-9 a-f 或 A-F
转义
\ 非换行符或十六进制数字 十六进制数字 1-6 次 空白
<whitespace-token>
空白
ws*
<whitespace-token>
<ident-token>
-- - a-z A-Z _ 或非 ASCII 转义 a-z A-Z 0-9 _ - 或非 ASCII 转义
<function-token>
<ident-token> (
<at-keyword-token>
@ <ident-token>
<hash-token>
# a-z A-Z 0-9 _ - 或非 ASCII 转义
<string-token>
" 非 " \ 或换行符 转义 \ 换行符 " ' 非 ' \ 或换行符 转义 \ 换行符 '
<url-token>
<ident-token "url"> ( ws* 非 " ' ( ) \ 空白或不可打印字符 转义 ws* )
<number-token>
+ - 数字 . 数字 数字 . 数字 e E + - 数字
<dimension-token>
<number-token> <ident-token>
<percentage-token>
<number-token> %
<CDO-token>
<!--
<CDC-token>
-->
<unicode-range-token>
U u + 十六进制数字 1-6 次 十六进制数字 1-5 次 ? 1 到 (6-digits) 次 十六进制数字 1-6 次 - 十六进制数字 1-6 次

4.2. 定义

本节定义了标记化阶段使用的若干术语。

下一个输入代码 点
输入流中尚未被消费的第一个代码点。
当前输入 代码点
最后一个已被消费的代码点。
重新消费当前输入代码点
将当前输入代码点推回输入流的前端, 这样,下次指示你消费下一个输入代码点时, 将改为重新消费当前输入代码 点。
EOF 代码点
一个概念上的代码点,表示输入流的末尾。 每当输入流为空时, 下一个输入 代码点始终是 EOF 代码点。
数字
介于 U+0030 DIGIT ZERO (0) 和 U+0039 DIGIT NINE (9) 之间(含两端)的代码点。
测试
十六进制数字
一个数字, 或介于 U+0041 LATIN CAPITAL LETTER A (A) 和 U+0046 LATIN CAPITAL LETTER F (F) 之间(含两端)的代码点, 或介于 U+0061 LATIN SMALL LETTER A (a) 和 U+0066 LATIN SMALL LETTER F (f) 之间(含两端)的代码点。
大写字母
介于 U+0041 LATIN CAPITAL LETTER A (A) 和 U+005A LATIN CAPITAL LETTER Z (Z) 之间(含两端)的代码点。
小写字母
介于 U+0061 LATIN SMALL LETTER A (a) 和 U+007A LATIN SMALL LETTER Z (z) 之间(含两端)的代码点。
字母
一个大写字母 或一个小写 字母。
非 ASCII ident 代码点
一个值为以下任意值的代码点:
  • U+00B7

  • 介于 U+00C0 和 U+00D6 之间

  • 介于 U+00D8 和 U+00F6 之间

  • 介于 U+00F8 和 U+037D 之间

  • 介于 U+037F 和 U+1FFF 之间

  • U+200C

  • U+200D

  • U+203F

  • U+2040

  • 介于 U+2070 和 U+218F 之间

  • 介于 U+2C00 和 U+2FEF 之间

  • 介于 U+3001 和 U+D7FF 之间

  • 介于 U+F900 和 U+FDCF 之间

  • 介于 U+FDF0 和 U+FFFD 之间

  • 大于或等于 U+10000

所有这些范围都包含端点。

测试
为什么专门是这些字符?

这与允许在 HTML 有效自定义元素名称中使用的非 ASCII 代码点列表 相匹配。 它排除了一些表现为空白的字符, 或可能在某些工具中导致渲染或解析问题的字符, 例如方向覆盖代码点。

请注意,这组限制 比 UAX 31 为标识符推荐的限制更宽松 (JavaScript 等语言使用它来限制其标识符语法), 因而允许诸如 以组合字符开始标识符之类的情况。 与 HTML 自定义元素名称保持一致 (从而可以为所有自定义元素编写选择器, 而无需使用转义) 被认为很有价值, 而 HTML 所限制的字符集合 很好地涵盖了“高价值”限制。

这些限制并不能避免所有可能令人困惑的渲染; 混合使用 LTR 和 RTL 文字的字符 在大多数文本编辑器中 仍可能导致意外的视觉换位, 例如。 源文本也可以在非 ident 上下文中包含受限字符: 例如,其中大多数在字符串中完全有效。 即使以会产生无效 CSS 的方式使用, 它们造成的解析错误也可能仅限于不重要的部分, 而它们对代码审查工具中源文本渲染的影响 却可能很大和/或具有恶意。 有关这类“源文本攻击”的更多详细信息, 请参阅这篇 Rust-lang 博客 文章 (存档)。

ident-start 代码点
一个字母, 一个非 ASCII ident 代码点, 或 U+005F LOW LINE (_)。
ident 代码 点
一个ident-start 代码点, 一个数字, 或 U+002D HYPHEN-MINUS (-)。
不可打印 代码点
介于 U+0000 NULL 和 U+0008 BACKSPACE 之间(含两端)的代码点, 或 U+000B LINE TABULATION, 或介于 U+000E SHIFT OUT 和 U+001F INFORMATION SEPARATOR ONE 之间(含两端)的代码点, 或 U+007F DELETE。
测试
换行符
U+000A LINE FEED。 请注意,U+000D CARRIAGE RETURN 和 U+000C FORM FEED 不包含在此定义中, 因为它们会在预处理期间转换为 U+000A LINE FEED。
空白
一个换行符、U+0009 CHARACTER TABULATION 或 U+0020 SPACE。
测试
允许的最大 代码点
Unicode 定义的最大代码点:U+10FFFF。
ident 序列
与 <ident-token> 具有相同语法的一系列代码点。

注:<at-keyword-token> 中 "@" 之后的部分, <hash-token>(类型标志为 "id")中 "#" 之后的部分, <function-token> 中 "(" 之前的部分, 以及 <dimension-token> 的单位 都是ident 序列。

4.3. 标记器算法

本节定义的算法将代码点流转换为标记 流。

4.3.1. 消费一个标记

本节描述如何从代码 点流中消费一个标记。 它还接受一个可选的布尔值 unicode ranges allowed, 默认为 false。 它将返回任意类型的单个标记。

消费注释。

消费下一个 输入代码点。

空白
尽可能多地消费空白。 返回一个 <whitespace-token>。
U+0022 QUOTATION MARK (")
消费一个 字符串标记 并返回它。
U+0023 NUMBER SIGN (#)
如果下一个 输入代码点是一个ident 代码点 或接下来的两个输入代码点 构成有效转义, 则:
  1. 创建一个 <hash-token>。
  2. 如果接下来的 3 个输入代码点会开始一个 ident 序列, 则将 <hash-token> 的类型标志设置为 "id"。
  3. 消费一个 ident 序列, 并将 <hash-token> 的值设置为返回的字符串。
  4. 返回 <hash-token>。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+0027 APOSTROPHE (')
消费一个 字符串标记 并返回它。
U+0028 LEFT PARENTHESIS (()
返回一个 <(-token>。
U+0029 RIGHT PARENTHESIS ())
返回一个 <)-token>。
U+002B PLUS SIGN (+)
如果输入流以数字开始, 则重新消费当前输入代码点, 消费一个 数值标记, 并返回它。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+002C COMMA (,)
返回一个 <comma-token>。
U+002D HYPHEN-MINUS (-)
如果输入流以数字开始, 则重新消费当前输入代码点, 消费一个 数值标记, 并返回它。

否则, 如果接下来的 2 个输入代码点是 U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), 则消费它们 并返回一个 <CDC-token>。

否则, 如果输入流以 ident 序列开始, 则重新消费当前输入代码点, 消费一个类 ident 标记, 并返回它。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+002E FULL STOP (.)
如果输入流以数字开始, 则重新消费当前输入代码点, 消费一个 数值标记, 并返回它。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+003A COLON (:)
返回一个 <colon-token>。
U+003B SEMICOLON (;)
返回一个 <semicolon-token>。
U+003C LESS-THAN SIGN (<)
如果接下来的 3 个 输入代码点是 U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), 则消费它们 并返回一个 <CDO-token>。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+0040 COMMERCIAL AT (@)
如果接下来的 3 个 输入代码点 会开始一个 ident 序列, 则消费一个 ident 序列, 创建一个 <at-keyword-token>,其值设置为返回的 值, 并返回它。

否则, 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+005B LEFT SQUARE BRACKET ([)
返回一个 <[-token>。
U+005C REVERSE SOLIDUS (\)
如果输入流以有效转义开始, 则重新消费当前输入代码点, 消费一个类 ident 标记, 并返回它。
测试

否则, 这是一个解析错误。 返回一个 <delim-token>, 其值设置为当前输入代码点。

U+005D RIGHT SQUARE BRACKET (])
返回一个 <]-token>。
U+007B LEFT CURLY BRACKET ({)
返回一个 <{-token>。
U+007D RIGHT CURLY BRACKET (})
返回一个 <}-token>。
数字
重新消费当前输入代码点, 消费一个 数值标记, 并返回它。
U+0055 LATIN CAPITAL LETTER U (U)
u+0075 LATIN LOWERCASE LETTER U (u)
如果 unicode ranges allowed 为 true 且输入流会开始一个 unicode-range, 则重新消费当前输入代码点, 消费一个 unicode-range 标记, 并返回它。

否则, 重新消费当前输入代码点, 消费一个类 ident 标记, 并返回它。

ident-start 代码点
重新消费当前输入代码点, 消费一个类 ident 标记, 并返回它。
EOF
返回一个 <EOF-token>。
其他任何内容
返回一个 <delim-token>, 其值设置为当前输入代码点。
测试

4.3.2. 消费注释

本节描述如何从代码点流中消费注释。 它不返回任何内容。

如果接下来的两个 输入代码点是 U+002F SOLIDUS (/) 后跟 U+002A ASTERISK (*), 则消费它们 以及之后直至并包括第一个后跟 U+002F SOLIDUS (/) 的 U+002A ASTERISK (*) 的所有代码点, 或直至 EOF 代码点。 返回此步骤的开头。

如果前一段通过消费 EOF 代码点而结束, 则这是一个解析错误。

不返回任何内容。

4.3.3. 消费一个数值标记

本节描述如何从代码点流中消费一个数值标记。 它返回 <number-token>、<percentage-token> 或 <dimension-token> 中的一个。

消费一个数字,并令 number 为结果。

如果接下来的 3 个 输入代码点会开始一个 ident 序列, 则:

  1. 创建一个与 number 具有相同值、类型标志和 符号字符的 <dimension-token>, 并将其单位初始设置为空字符串。
  2. 消费一个 ident 序列。 将 <dimension-token> 的单位设置为返回值。
  3. 返回 <dimension-token>。

否则, 如果下一个输入 代码点是 U+0025 PERCENTAGE SIGN (%), 则消费它。 创建一个与 number 具有相同值和符号字符的 <percentage-token>, 并返回它。

否则, 创建一个与 number 具有相同值、类型标志和符号 字符的 <number-token>, 并返回它。

4.3.4. 消费一个类 ident 标记

本节描述如何从代码 点流中消费一个类 ident 标记。 它返回 <ident-token>、<function-token>、<url-token> 或 <bad-url-token>。

消费一个 ident 序列,并令 string 为结果。

如果 string 的值与 "url" ASCII 大小写不敏感匹配, 且下一个 输入代码点是 U+0028 LEFT PARENTHESIS ((), 则消费它。 当接下来的两个输入代码点都是空白时, 消费下一个输入代码点。 如果接下来的一个或两个输入代码点是 U+0022 QUOTATION MARK (")、 U+0027 APOSTROPHE ('), 或空白后跟 U+0022 QUOTATION MARK (") 或 U+0027 APOSTROPHE ('), 则创建一个 <function-token>, 其值设置为 string 并返回它。 否则, 消费一个 url 标记, 并返回它。

否则, 如果下一个输入 代码点是 U+0028 LEFT PARENTHESIS ((), 则消费它。 创建一个 <function-token>, 其值设置为 string 并返回它。

否则, 创建一个 <ident-token>, 其值设置为 string 并返回它。

4.3.5. 消费一个字符串标记

本节描述如何从代码点流中消费一个字符串标记。 它返回 <string-token> 或 <bad-string-token>。

调用此算法时可以传入一个 ending code point, 它表示结束字符串的代码点。 如果未指定 ending code point, 则使用当前 输入代码点。

初始创建一个值为空字符串的 <string-token>。

从流中重复消费下一个输入代码点:

ending code point
返回 <string-token>。
EOF
这是一个解析错误。 返回 <string-token>。
换行符
这是一个解析错误。 重新消费当前输入代码点, 创建一个 <bad-string-token>,并返回它。
U+005C REVERSE SOLIDUS (\)
如果下一个 输入代码点是 EOF, 则不执行任何操作。

否则, 如果下一个输入代码点是换行符, 则消费它。

否则, (流以有效 转义开始) 消费一个转义代码点 并将返回的代码点附加到 <string-token> 的值。

其他任何内容
将当前输入代码点附加到 <string-token> 的值。
测试

4.3.6. 消费一个 url 标记

本节描述如何从代码点流中消费一个 url 标记。 它返回 <url-token> 或 <bad-url-token>。

注:此算法假定初始的 "url(" 已 被消费。 此算法还假定调用它是为了消费一个“不带引号”的值, 例如 url(foo)。 带引号的值,例如 url("foo"), 会被解析为 <function-token>。 消费一个类 ident 标记会自动处理这种 区别; 否则不应该直接调用此算法。

  1. 初始创建一个值为空字符串的 <url-token>。
  2. 尽可能多地消费空白。
  3. 从流中重复消费下一个输入代码点:
    U+0029 RIGHT PARENTHESIS ())
    返回 <url-token>。
    EOF
    这是一个解析错误。 返回 <url-token>。
    空白
    尽可能多地消费空白。 如果下一个输入代码点是 U+0029 RIGHT PARENTHESIS ()) 或 EOF, 则消费它并返回 <url-token> (如果遇到 EOF,则这是一个解析错误); 否则, 消费错误 url 的剩余部分, 创建一个 <bad-url-token>, 并返回它。
    U+0022 QUOTATION MARK (")
    U+0027 APOSTROPHE (')
    U+0028 LEFT PARENTHESIS (()
    不可打印代码点
    这是一个解析错误。 消费错误 url 的剩余部分, 创建一个 <bad-url-token>, 并返回它。
    U+005C REVERSE SOLIDUS (\)
    如果流以有效转义开始, 则消费一个转义代码点 并将返回的代码点附加到 <url-token> 的值。

    否则, 这是一个解析 错误。 消费错误 url 的剩余部分, 创建一个 <bad-url-token>, 并返回它。

    其他任何内容
    将当前输入代码点 附加到 <url-token> 的值。
测试

4.3.7. 消费一个转义代码点

本节描述如何消费一个转义代码点。 它假定 U+005C REVERSE SOLIDUS (\) 已经被消费 并且下一个输入代码点已经验证 为有效转义的一部分。 它将返回一个代码点。

消费下一个 输入代码点。

十六进制数字
尽可能多地消费十六进制数字, 但不超过 5 个。 请注意,这意味着总共消费了 1-6 个十六进制数字。 如果下一个 输入代码点是 空白, 则也消费它。 将十六进制数字解释为一个十六进制数。 如果此数字为零, 或对应于代理项, 或大于允许的最大代码点, 则返回 U+FFFD REPLACEMENT CHARACTER (�)。 否则,返回具有该值的代码点。
EOF
这是一个解析错误。 返回 U+FFFD REPLACEMENT CHARACTER (�)。
其他任何内容
返回当前输入代码点。
测试

4.3.8. 检查两个代码点是否构成有效转义

本节描述如何检查两个代码点是否构成有效 转义。 此处描述的算法可以显式传入两个代码点来调用, 也可以直接传入输入流来调用。 在后一种情况下,所指的两个代码点是 当前 输入代码点 和下一个 输入代码点, 顺序如此。

注:此算法不会消费任何额外的代码 点。

如果第一个代码点不是 U+005C REVERSE SOLIDUS (\), 则返回 false。

否则, 如果第二个代码点是换行符, 则返回 false。

否则,返回 true。

4.3.9. 检查三个代码点是否会开始一个 ident 序列

本节描述如何 检查三个代码点是否会 开始一个ident 序列。 此处描述的算法可以显式传入三个代码点来调用, 也可以直接传入输入流来调用。 在后一种情况下,所指的三个代码点是 当前 输入代码点 和接下来的两个 输入代码点, 顺序如此。

注:此算法不会消费任何额外的代码 点。

查看第一个代码点:

U+002D HYPHEN-MINUS
如果第二个代码点是一个ident-start 代码点 或 U+002D HYPHEN-MINUS, 或第二个和第三个代码点构成有效转义, 则返回 true。 否则,返回 false。
ident-start 代码点
返回 true。
U+005C REVERSE SOLIDUS (\)
如果第一个和第二个代码点构成有效转义, 则返回 true。 否则,返回 false。
其他任何内容
返回 false。
测试

4.3.10. 检查三个代码点是否会开始一个数字

本节描述如何检查三个代码点是否会 开始一个数字。 此处描述的算法可以显式传入三个代码点来调用, 也可以直接传入输入流来调用。 在后一种情况下,所指的三个代码点是 当前 输入代码点 和接下来的两个 输入代码点, 顺序如此。

注:此算法不会消费任何额外的代码 点。

查看第一个代码点:

U+002B PLUS SIGN (+)
U+002D HYPHEN-MINUS (-)
如果第二个代码点 是一个数字, 则返回 true。

否则, 如果第二个代码点 是 U+002E FULL STOP (.) 且第三个代码点 是一个数字, 则返回 true。

否则,返回 false。

U+002E FULL STOP (.)
如果第二个代码点 是一个数字, 则返回 true。 否则,返回 false。
数字
返回 true。
其他任何内容
返回 false。

4.3.11. 检查三个代码点是否会开始一个 unicode-range

本节描述如何 检查三个代码点 是否会开始一个 unicode-range。 此处描述的算法可以显式传入三个代码点来调用, 也可以直接传入输入流来调用。 在后一种情况下,所指的三个代码点是 当前 输入代码点 和接下来的两个 输入代码点, 顺序如此。

注:此算法不会消费任何额外的代码 点。

如果以下所有条件均为 true:

则返回 true。

否则返回 false。

4.3.12. 消费一个 ident 序列

本节描述如何从代码点流中消费一个 ident 序列。 它返回一个字符串,其中包含 从第一个代码点开始,可由流中相邻代码点形成的 最长名称。

注:此算法不会验证 为确保返回的代码点会 构成 <ident-token> 所必需的前几个代码点。 如果这正是预期用途, 请确保流在调用此算法之前以 ident 序列开始 。

令 result 初始为空字符串。

从流中重复消费下一个输入代码点:

ident 代码点
将代码点附加到 result。
流以有效转义开始
消费一个转义代码点。 将返回的代码点附加到 result。
其他任何内容
重新消费当前输入代码点。 返回 result。

4.3.13. 消费一个数字

本节描述如何从代码点流中消费一个数字。 它返回一个数值 value, 一个值为 "integer" 或 "number" 的字符串 type, 以及一个值为 "+"、"-" 或缺失的可选 sign character。

注:此算法不会验证 为确保能够从流中获得数字所必需的前几个代码点 。 请确保流在调用此算法之前以数字开始 。

按顺序执行以下步骤:

  1. 令 type 为字符串 "integer"。 令 number part 和 exponent part 为空字符串。
  2. 如果下一个 输入代码点是 U+002B PLUS SIGN (+) 或 U+002D HYPHEN-MINUS (-), 则消费它。 将其附加到 number part 并将 sign character 设置为它。
  3. 当下一个输入代码点是一个数字时, 消费它并将其附加到 number part。
  4. 如果接下来的 2 个 输入代码点是 U+002E FULL STOP (.) 后跟一个数字, 则:
    1. 消费下一个输入代码点并将其附加到 number part。
    2. 当下一个输入代码点是一个数字时,消费它并将其附加到 number part。
    3. 将 type 设置为 "number"。
  5. 如果接下来的 2 个 或 3 个输入代码点是 U+0045 LATIN CAPITAL LETTER E (E) 或 U+0065 LATIN SMALL LETTER E (e), 可选地后跟 U+002D HYPHEN-MINUS (-) 或 U+002B PLUS SIGN (+), 再后跟一个数字, 则:
    1. 消费下一个输入代码点。
    2. 如果下一个输入代码点是 "+" 或 "-", 则消费它并将其附加到 exponent part。
    3. 当下一个输入代码点是一个数字时,消费它并将其附加到 exponent part。
    4. 将 type 设置为 "number"。
  6. 令 value 为将 number part 解释为十进制数的结果。

    如果 exponent part 非空, 则将其解释为十进制整数, 然后计算 10 的该结果次幂, 将其乘以 value, 并将 value 设置为该结果。

  7. 返回 value、type 和 sign character。
测试

4.3.14. 消费一个 unicode-range 标记

本节描述如何消费一个 unicode-range 标记 从代码点流中。 它返回一个 <unicode-range-token>。

注:此算法不会验证 为确保返回的代码点 会构成 <unicode-range-token> 所必需的前几个代码点。 请确保流在调用此算法之前会开始一个 unicode-range 。

注:在正常情况下,标记器不会产生此标记 。 此算法仅在 消费 unicode-range 描述符的值期间调用, 而该算法本身也仅作为一种特殊情况被调用, 用于解析 unicode-range 描述符; 整个语言中仅有这一次调用, 是由于早期 CSS 中糟糕的语法设计。

  1. 消费接下来的两个输入代码点并丢弃它们。

  2. 尽可能多地消费十六进制数字, 但不超过 6 个。 如果消费的十六进制数字少于 6 个, 则尽可能多地消费 U+003F QUESTION MARK (?) 代码点, 但数量不得超过使十六进制数字 与 U+003F QUESTION MARK (?) 代码点的总数 等于 6 所需的数量。

    令 first segment 为已消费的代码点。

  3. 如果 first segment 包含任何问号代码点,则:

    1. 将 first segment 中的问号替换为 U+0030 DIGIT ZERO (0) 代码点, 并将结果解释为十六进制数。 令其为 start of range。

    2. 将 first segment 中的问号替换为 U+0046 LATIN CAPITAL LETTER F (F) 代码点, 并将结果解释为十六进制数。 令其为 end of range。

    3. 返回一个新的 <unicode-range-token>,从 start of range 开始并在 end of range 结束。

  4. 否则,将 first segment 解释为十六进制数, 并令结果为 start of range。

  5. 如果接下来的 2 个输入代码点是 U+002D HYPHEN-MINUS (-) 后跟一个十六进制数字, 则:

    1. 消费下一个输入代码点。

    2. 尽可能多地消费十六进制 数字,但不超过 6 个。 将已消费的代码点解释为十六进制数。 令其为 end of range。

    3. 返回一个新的 <unicode-range-token>,从 start of range 开始并在 end of range 结束。

  6. 否则,返回一个新的 <unicode-range-token>,其起点和终点均 为 start of range。

4.3.15. 消费错误 url 的剩余部分

本节描述如何从代码 点流中消费错误 url 的剩余部分, 在标记器意识到自己正处于 <bad-url-token> 而不是 <url-token> 中间后进行“清理”。 它不返回任何内容; 其唯一用途是消费足够多的输入流以到达恢复点, 在那里可以恢复正常标记化。

从流中重复消费下一个输入代码点:

U+0029 RIGHT PARENTHESIS ())
EOF
返回。
输入流以有效转义开始
消费一个转义代码点。 这允许遇到转义的右圆括号("\)")而不会结束 <bad-url-token>。 除此之外,这与“其他任何内容”分支完全相同。
其他任何内容
不执行任何操作。

5. 解析

CSS 解析器将标记流 (由标记化过程产生, 如本规范前文所定义) 转换为若干 CSS 构造中的一个或多个 (具体取决于调用了哪个解析算法)。

5.1. 解析器铁路图

本节是非规范性的。

本节以铁路图的形式 提供解析器的信息性视图。

这些图是信息性的且不完整的; 它们描述“正确”样式表的语法, 但完全不描述错误处理。 提供这些图只是为了更容易直观掌握语法。

样式表
<whitespace-token> <CDC-token> <CDO-token> 限定规则 At-rule
At-rule
<at-keyword-token> 组件值 {} 块 ;
限定规则
组件值 {} 块
{} 块
{ ws* 声明 ; At-rule 限定规则 ws* ws* }
声明
<ident-token> ws* : 组件值 !important
!important
! ws* <ident-token "important"> ws*
组件值
保留标记 简单块 函数块
简单块
{ 组件值 } ( 组件值 ) [ 组件值 ]
函数块
<function-token> 组件值 )

5.2. CSS 解析结果

解析结果可以是以下任意一种 (或这些结果的列表):

样式表

样式表具有一个规则列表。

规则

规则是 at-rule 或限定规则之一。

at-rule
at-rule 具有一个名称,该名称是字符串, 以及一个由组件值列表组成的前奏。 块 at-rule (以 {}-block 结束) 还将具有 一个声明列表 和一个子规则列表。 (语句 at-rule 以分号结束, 则不会具有这些内容。)
限定规则
限定规则具有 一个由组件值列表组成的前奏、 一个声明列表, 以及一个子规则列表。

注:大多数限定规则都是样式规则, 其中前奏是选择器 [selectors-4] 而其声明是属性。

声明
声明具有一个名称,该名称是字符串, 以及一个由组件值列表组成的值, 还有一个初始未设置的 important 标志。 它还具有一个可选的 original text,该文本是一个字符串 (仅为少数声明捕获)。

声明还进一步分类 为属性声明或描述符 声明, 前者设置 CSS 属性 并且最常出现在限定规则中, 后者设置 CSS 描述符, 它仅出现在at-rule中。 (这种分类不会发生在语法层面; 相反,它取决于声明出现的位置, 并由定义给定规则的相应规范定义。)

组件值
组件值是保留标记、 函数、 或简单块之一。
保留标记
标记器产生的任何标记, 除 <function-token>、 <{-token>、 <(-token>、 和 <[-token> 之外。

注:上面列出的非保留标记 总是被消费到更高级别的对象中, 即函数或简单块, 因此它们本身永远不会出现在任何解析器输出中。

注:标记 <}-token>、<)-token>、<]-token>、<bad-string-token> 和 <bad-url-token> 始终是解析错误, 但本规范会将它们保留在标记流中,以允许其他规范, 例如媒体查询, 定义比直接丢弃整个声明或块 更细粒度的错误处理。

函数
函数具有一个名称 和一个由组件值列表组成的值。
简单 块
{}-block
[]-block
()-block
简单块具有关联标记(<[-token>、<(-token> 或 <{-token> 之一) 以及一个由组件值列表组成的值。

{}-block、[]-block 和 ()-block 专门指 具有相应 关联标记的简单块。

测试

5.3. 标记流

标记 流是一个结构, 表示标记和/或组件值的流。 它具有以下项:

标记

一个由标记 和/或组件 值组成的列表。

注:为 简单起见,本规范假定 输入流已经完全标记化 然后才开始解析。 但是,解析算法只使用一个“前瞻”标记, 因此在实践中,标记化和解析 可以同步进行。

索引

指向标记的索引, 表示解析的进度。 它最初从 0 开始。

注:除了标记位置之外, 索引 永远不会后退。 因此,标记中已处理的前缀 可以在处理时立即丢弃。

已标记索引

一个由 索引值组成的栈, 表示解析器可能返回的位置。 它最初为空。

CSS 中有少数位置 需要引用 为声明值解析的精确文本 (而不只是从该文本产生了哪些标记)。 这里的算法结构没有显式描述这一点, 但标记流 因此必须 能够按需重现声明的原始文本。 有关何时需要这样做的详细信息,请参阅消费一个 声明 。

可以对标记流执行若干操作:

下一个标记

标记中位于索引处的项。

如果该索引超出列表末尾的范围, 则改为一个 <eof-token>。

空

如果下一个标记是 <eof-token>,则标记流为空 。

消费一个标记

令 token 为下一个标记。 将索引加一, 然后返回 token。

丢弃一个标记

如果标记 流不是空, 则将索引加一。

标记位置

将索引 附加到已标记索引。

恢复标记位置

从已标记索引中弹出, 并将索引设置为弹出的值。

丢弃标记位置

从已标记索引中弹出, 并且不对弹出的值执行任何操作。

丢弃空白

当下一个标记是 <whitespace-token> 时, 丢弃一个标记。

处理

要进行处理, 给定以下标记类型及关联操作列表, 执行与下一个标记关联的操作。 重复执行,直到其中一个操作返回某个内容, 然后返回该内容。

<eof-token> 是一个概念性标记, 实际上并非由标记器产生, 用于指示标记流已耗尽。

5.4. 解析器入口点

本节定义的算法从 CSS 标记列表 生成高级 CSS 对象。

此处的算法以标记流作为输入进行操作, 但为方便起见, 也可以使用若干其他值类型来调用。

要将给定的 input 规范化为标记流:

  1. 如果 input 已经是标记流, 则返回它。

  2. 如果 input 是 CSS 标记和/或组件值的列表, 则创建一个新的标记流, 以 input 作为其标记, 并返回它。

  3. 如果 input 是一个字符串, 则从 input 筛选代码点, 标记化结果, 并返回标记流。

  4. 断言:只应将上述类型作为 input 传入。

注:其他规范可以为 自身用途定义额外的入口点。

以下注释或许应该在相关规范中转换为规范性文本, 并与本规范的术语挂钩:

5.4.1. 根据 CSS 语法解析某内容

通常需要解析字符串或标记列表 以查看它是否匹配某个 CSS 语法, 如果匹配, 则根据该语法将其解构。 本节为此类操作提供一个通用钩子。 它应以类似如下方式调用: “将 foo 解析为 CSS <color>”,或类似方式。

如果输入不匹配提供的语法, 此算法返回失败, 否则返回根据该语法解析输入的结果, 这是与所提供语法规范相对应的未指定结构。 返回值只能由规范文本进行交互, 在这种情况下,表示形式的歧义不会造成问题。 如果其目的是在规范语言之外公开, 使用结果的规范必须明确将其转换为明确定义的表示形式, 例如通过调用 CSS 序列化算法 (例如“序列化为 CSS <string> 值”)。

注:此算法 以及根据 CSS 语法解析逗号分隔列表 通常是其他规范唯一想要调用的解析算法。 其余解析算法主要用于 [CSSOM] 以及相关的“显式构造 CSS 结构”情况。 如果你认为需要使用其他算法之一, 请先向 CSSWG 咨询指导。

给定 input 和一个 CSS grammar 产生式,要根据 CSS 语法解析某内容 (也简称为解析) :
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 解析组件值列表, 并令 result 为返回值。
  3. 尝试将 result 与 grammar 匹配。 如果成功, 返回匹配结果; 否则,返回失败。

5.4.2. 根据 CSS 语法解析逗号分隔列表

当然可以根据包含逗号的语法 解析一个值, 但如果值的任何部分解析失败, 整个内容都会解析失败, 并返回失败。

有时这正是所需行为 (例如在列表值 CSS 属性中); 但在其他时候, 最好让值中每个逗号分隔的子部分单独解析, 对成功解析的部分采用一种处理方式, 对解析失败的部分采用另一种处理方式 (通常忽略它们, 例如在 <img sizes> 中)。

此算法提供了一个简单的钩子来实现这一点。 它返回一个由“顶层”逗号分割的值列表, 其中每个值要么是失败 (如果解析失败) 要么是解析结果 (一种未指定结构, 如解析算法中所述)。

给定 input 和一个 CSS grammar 产生式,要根据 CSS 语法解析逗号分隔列表 (也称为解析列表) :
  1. 规范化 input, 并将 input 设置为结果。
  2. 如果 input 仅包含 <whitespace-token>, 则返回一个空列表。
  3. 从 input 解析逗号分隔的组件值 列表, 并令 list 为返回值。
  4. 对 list 中的每个 item, 将 item 替换为 使用 grammar 解析 item 的结果。
  5. 返回 list。

5.4.3. 解析样式表

给定可选的 url location,要从 input 解析样式表:
  1. 如果 input 是样式表的字节流, 则从 input 解码字节, 并将 input 设置为结果。
  2. 规范化 input, 并将 input 设置为结果。
  3. 创建一个新的样式表, 将其位置设置为 location (如果未传入 location,则为 null)。
  4. 从 input 消费样式表内容, 并将样式表的规则设置为结果。
  5. 返回样式表。

5.4.4. 解析样式表内容

要从 input 解析 样式表内容:
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 消费样式表内容, 并返回结果。

5.4.5. 解析块的内容

要从 input 解析块的 内容:
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 消费块的内容, 并返回结果。

5.4.6. 解析规则

要从 input 解析规则:
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 丢弃空白。
  3. 如果来自 input 的下一个标记是 <EOF-token>, 则返回语法错误。

    否则, 如果来自 input 的下一个标记是 <at-keyword-token>, 则从 input 消费一个 at-rule, 并令 rule 为返回值。

    否则, 从 input 消费一个限定规则 并令 rule 为返回值。 如果返回的是什么都没有或无效规则错误, 则返回语法错误。

  4. 从 input 丢弃空白。
  5. 如果来自 input 的下一个标记是 <EOF-token>, 则返回 rule。 否则,返回语法错误。

5.4.7. 解析声明

注:与“解析声明列表”不同, 此操作只解析一个声明,而不解析 at-rule。

要从 input 解析 声明:
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 丢弃空白。
  3. 从 input 消费一个 声明。 如果返回了任何内容,则返回它。 否则,返回语法错误。

5.4.8. 解析组件值

要从 input 解析组件 值:
  1. 规范化 input, 并将 input 设置为结果。
  2. 从 input 丢弃空白。
  3. 如果 input 是空, 则返回语法错误。
  4. 从 input 消费一个组件值 并令 value 为返回值。
  5. 从 input 丢弃空白。
  6. 如果 input 是空, 则返回 value。 否则, 返回语法错误。

5.4.9. 解析组件值列表

要从 input 解析 组件值列表:
  1. 规范化 input, 并将 input 设置为结果。

  2. 从 input 消费组件值列表, 并返回结果。

5.4.10. 解析逗号分隔的组件值列表

要从 input 解析逗号分隔的组件 值列表:
  1. 规范化 input, 并将 input 设置为结果。

  2. 令 groups 为一个空列表。

  3. 当 input 不是空时:

    1. 从 input 消费组件 值列表, 以 <comma-token> 作为停止标记, 并将结果附加到 groups。

    2. 从 input 丢弃一个标记。

  4. 返回 groups。

5.5. 解析器算法

以下算法构成解析器。 它们由上述解析器入口点调用, 通常不应由其他规范直接调用。

请注意,CSS 解析区分大小写, 并且在至少某些情况下,检查给定上下文中构造的有效性 必须在解析期间进行。 本规范有意不指定 应如何传递足够的上下文 以启用有效性检查。

5.5.1. 消费样式表的内容

要从标记流 input 中消费 样式表的内容:

令 rules 为一个初始为空的规则列表。

处理 input:

<whitespace-token>
从 input 丢弃一个标记。
<EOF-token>
返回 rules。
<CDO-token>
<CDC-token>
从 input 丢弃一个标记。
这是做什么的?

在 CSS 最初被引入时, 较旧的浏览器会将 style 元素视为未知元素 。 为了避免让这些旧版浏览器 在页面中显示其内容, 通常会将样式表包裹 在 HTML 注释中, 而较新的浏览器则会直接忽略 HTML 注释语法。 这一要求一直延续至今, 数十年后仍然如此。

同样的做法也用于 script 元素, 其中 HTML 注释语法在 JS 中被视为行注释 (类似于 //) ,原因相同。

<at-keyword-token>
从 input 消费一个 at-rule。 如果返回了任何内容, 将其附加到 rules。
其他任何内容
从 input 消费 一个限定规则。 如果返回了一个规则, 将其附加到 rules。

5.5.2. 消费一个 at-rule

给定可选的 bool nested(默认为 false),要从标记流 input 中消费一个 at-rule :

断言:下一个标记是 <at-keyword-token>。

从 input 消费一个标记, 并令 rule 为一个新的at-rule, 其名称设置为返回标记的值, 其前奏初始设置为空列表, 且没有声明或子规则。

处理 input:

<semicolon-token>
<EOF-token>
从 input 丢弃一个标记。 如果 rule 在当前上下文中有效, 返回它; 否则不返回任何内容。
<}-token>
如果 nested 为 true:
  • 如果 rule 在当前上下文中有效, 返回它。

  • 否则,不返回任何内容。

否则,消费一个标记 并将结果附加到 rule 的前奏。

<{-token>
从 input 消费一个块, 并将结果赋给 rule 的子规则。

注:如果结果包含列表形式的 声明, 它们在 CSSOM 中如何具体化 取决于规则。 有些规则会将它们全部转换为嵌套声明规则, 另一些会将它们全部视为声明, 还有一些会以不同于其余项的方式处理第一项。

如果 rule 在当前上下文中有效, 返回它。 否则不返回任何内容。

其他任何内容
从 input 消费一个组件值 并将返回值附加到 rule 的前奏。

5.5.3. 消费一个限定规则

给定可选的标记 stop token 和可选的 bool nested(默认为 false),要从标记流 input 中消费一个 限定规则:

令 rule 为一个新的限定规则, 其前奏、声明和子规则 初始均设置为空列表。

处理 input:

<EOF-token>
stop token(如果已传入)
这是一个解析错误。 不返回任何内容。
<}-token>
这是一个解析错误。 如果 nested 为 true, 不返回任何内容。 否则, 消费一个标记 并将结果附加到 rule 的前奏。
<{-token>
如果 rule 的前奏中前两个非 <whitespace-token> 值 是 一个值以 "--" 开头的 <ident-token> 后跟一个 <colon-token>,则:
为什么要进行此检查?

声明和限定规则 在允许的语法中通常不会重叠。 当前定义的 CSS 属性都不允许其值中包含 {}-block, 因此 foo:bar {}; 肯定是规则, 而 foo: bar; 肯定是属性。 即使未来某个 CSS 属性允许其值中包含 {}-block, 所允许的语法也会限制为 {}-block 构成整个值, 例如 foo: {...};, 它保证不会是有效规则, 因为 : 后面没有 ident 或函数 来将其标记为伪类。

这使我们能够在同一上下文中混合声明和规则: 我们首先尝试将某内容解析为声明, 如果这样不能得到有效声明, 则改为重新将其解析为规则。 意外无效的声明会改为解析成规则, 但这没有问题: 解析器会在声明的结束分号处停止 并将其视为无效规则。 (或者,如果属性包含 {}-block, 会在分号*之前*停止, 仍将其视为无效规则, 然后下一次尝试解析某内容时 会将孤立的分号作为无效内容丢弃。) 因此,无论哪种情况,消费的标记总量都相同。

然而,自定义属性并没有 CSSWG 仔细审查其语法。 作者可以编写一个自定义属性, 其值接受 {}-block, 甚至与其他内容组合; 如果该自定义属性随后无效 (例如由于错误编写的 var() 函数), 当它被重新解析为规则时 会在 {}-block 处提前停止。 自定义属性值中剩余的标记 随后会作为新的构造进行解析, 可能导致意外的声明或规则 被创建。

为了避免这种(诚然非常边缘的)情况, 我们从自定义属性的语法 中减去限定规则的语法; 如果你处于允许属性和规则混合的上下文中, 并且不知何故最终解析出一个 看起来像自定义属性的规则, 那就说明你弄错了, 应改为消费整个自定义属性 (一直到结束分号)。

(如果我们处于不允许属性的上下文中, 那么如果规则看起来像自定义属性, 我们就直接丢弃该规则。 这确保 --foo:hover { color: blue; } 在任何地方都始终无效, 而不会为了寻找不存在的结束分号 而可能消费样式表的大量内容。)

否则,从 input 消费一个 块, 并令 child rules 为结果。 如果 child rules 的第一项是一个由声明组成的列表, 将其从 child rules 中移除 并将其赋给 rule 的声明。 如果 child rules 中任何剩余项是由声明组成的列表, 将它们替换为嵌套声明规则, 并使该列表成为其唯一子项。 将 child rules 赋给 rule 的子规则。

如果 rule 在当前上下文中有效, 返回它; 否则返回一个无效规则错误。

测试
其他任何内容
从 input 消费一个组件值 并将结果附加到 rule 的前奏。
测试

5.5.4. 消费一个块

要从标记流 input 中消费一个块:

断言:下一个标记 是 <{-token>。

从 input 丢弃一个标记。 从 input 消费 块的内容 并令 rules 为结果。 从 input 丢弃一个标记。

返回 rules。

5.5.5. 消费块的内容

要从标记流 input 中消费 块的内容:

注:此算法返回一个列表, 由规则和列表形式的声明组成。 根据父上下文, 一个由声明组成的列表 可能在 CSSOM 中具体化为 CSSStyleDeclaration, 或具体化为一个 CSSNestedDeclarations 规则。

令 rules 为一个空列表, 其中包含规则 或由声明组成的列表。

令 decls 为一个空列表,其中包含声明。

处理 input:

<whitespace-token>
<semicolon-token>
从 input 丢弃一个标记。
<EOF-token>
<}-token>
返回 rules。
<at-keyword-token>
如果 decls 非空, 将其附加到 rules, 并将 decls 设置为一个新的空列表,其中包含声明。

从 input 消费一个 at-rule, 并将 nested 设置为 true。 如果返回了一个规则, 将其附加到 rules。

其他任何内容
标记位置 input。

从 input 消费一个 声明, 并将 nested 设置为 true。 如果返回了一个声明, 将其附加到 decls, 并从 input 丢弃标记位置。

否则,从 input 恢复标记位置, 然后从 input 消费一个限定规则, 并将 nested 设置为 true, 且以 <semicolon-token> 作为 stop token。

如果未返回任何内容

不执行任何操作

如果返回了无效规则错误

如果 decls 非空, 将 decls 附加到 rules, 并将 decls 设置为一个新的空列表,其中包含声明。 (否则,不执行任何操作。)

如果返回了一个规则

如果 decls 非空, 将 decls 附加到 rules, 并将 decls 设置为一个新的空列表,其中包含声明。 将规则附加到 rules。

实现注释

本规范与许多 CSS 规范一样, 编写时优先考虑可理解性 而不是效率。 许多算法, 尤其是上述“先解析为声明,再解析为规则”的行为, 如果按描述直接实现, 可能相当低效。

不过,该行为经过精心编写, 以尽可能允许“提前退出”。 特别是, 大致按可能发生退出的顺序:

类似地, 即使解析要求被指定为 在解析过程中依赖于检查声明的语法, 一个通用处理器 若尝试在通用 CSS 语法之上 实现非 CSS 语言, 仍然只需验证声明 是否以 ident、冒号开头, 然后要么仅包含一个 {}-block, 要么完全不包含 {}-block。 在类似 foo:hover ... {} 的情况下, 它们只会比了解语法的实现 多花一点解析时间, 因为它们无法在第一个标记处提前退出。

测试

5.5.6. 消费一个声明

给定可选的 bool nested(默认为 false),要从标记流 input 中消费一个 声明 :

令 decl 为一个新的声明, 其名称初始为空 且值设置为空列表。

  1. 如果下一个标记是 <ident-token>, 从 input 消费一个标记 并将 decl 的名称 设置为该标记的值。

    否则, 从 input 消费错误 声明的剩余部分, 使用 nested, 然后不返回任何内容。

  2. 从 input 丢弃空白。
  3. 如果下一个标记是 <colon-token>, 从 input 丢弃一个标记。

    否则, 从 input 消费错误 声明的剩余部分, 使用 nested, 然后不返回任何内容。

  4. 从 input 丢弃空白。
  5. 从 input 消费组件值列表, 使用 nested, 并以 <semicolon-token> 作为停止标记, 然后将 decl 的值设置为结果。
  6. 如果 decl 的值中最后两个非 <whitespace-token> 是一个值为 "!" 的 <delim-token> 后跟一个其值与 "important" ASCII 大小写不敏感匹配的 <ident-token>, 将它们从 decl 的值中移除 并设置 decl 的 important 标志。
  7. 当 decl 的值中的最后一项是 <whitespace-token> 时, 移除该标记。
  8. 如果 decl 的名称是自定义属性名称字符串, 则将 decl 的 original text 设置为原始源文本字符串中 与 decl 的值的标记 相对应的片段。

    否则,如果 decl 的值包含顶层简单块, 其关联标记为 <{-token>, 并且还包含任何其他非 <whitespace-token> 值, 则不返回任何内容。 (也就是说,顶层 {}-block 仅允许 作为非自定义属性的整个值。)

    否则,如果 decl 的名称与 "unicode-range" ASCII 大小写不敏感匹配, 从与消费组件值列表调用所返回标记 相对应的原始源文本字符串片段中 消费 unicode-range 描述符的值, 并将 decl 的值替换为结果。

    测试
  9. 如果 decl 在当前上下文中有效, 返回它; 否则不返回任何内容。
给定 bool nested,要从标记流 input 中消费错误声明的剩余部分 :

处理 input:

<eof-token>
<semicolon-token>

从 input 丢弃一个标记, 然后不返回任何内容。

<}-token>

如果 nested 为 true, 不返回任何内容。 否则, 丢弃一个标记。

其他任何内容

从 input 消费一个组件值, 然后不执行任何操作。

5.5.7. 消费组件值列表

给定可选的标记 stop token 和可选的 boolean nested(默认为 false),要从标记流 input 中消费 组件值列表:

令 values 为一个空列表,其中包含组件值。

处理 input:

<eof-token>
stop token(如果已传入)

返回 values。

<}-token>

如果 nested 为 true, 返回 values。

否则, 这是一个解析错误。 从 input 消费一个标记 并将结果附加到 values。

其他任何内容

从 input 消费一个组件值, 并将结果附加到 values。

测试

5.5.8. 消费一个组件值

要从标记流 input 中消费一个 组件值:

处理 input:

<{-token>
<[-token>
<(-token>

从 input 消费一个 简单块 并返回结果。

<function-token>

从 input 消费一个 函数 并返回结果。

其他任何内容

从 input 消费一个标记 并返回结果。

5.5.9. 消费一个简单块

要从标记流 input 中消费一个简单 块:

断言:input 的下一个标记是 <{-token>、 <[-token>, 或 <(-token>。

令 ending token 为下一个标记的镜像变体。 (例如,如果调用时使用的是 <[-token>, 则 ending token 为 <]-token>。)

令 block 为一个新的简单 块, 将其关联标记设置为下一个标记, 并将其值初始设置为空列表。

从 input 丢弃一个标记。

处理 input:

<eof-token>
ending token

从 input 丢弃一个标记。 返回 block。

其他任何内容

从 input 消费一个组件值 并将结果附加到 block 的值。

5.5.10. 消费一个函数

要从标记流 input 中消费一个 函数:

断言:下一个标记是 <function-token>。

从 input 消费一个标记, 并令 function 为一个新函数, 其名称等于返回标记的值, 且其值设置为空列表。

处理 input:

<eof-token>
<)-token>

从 input 丢弃一个标记。 返回 function。

其他任何内容

从 input 消费一个组件值 并将结果附加到 function 的值。

5.5.11. 消费 unicode-range 值

要从字符串 input string 中消费 unicode-range 描述符的值:

  1. 令 tokens 为对 input string 进行标记化的结果, 并将 unicode ranges allowed 设置为 true。

  2. 从 tokens 消费组件值列表, 并返回结果。

注:此算法之所以存在, 是由于早期 CSS 中的设计错误。 永远不应复制这种设计。

6. An+B 微语法

CSS 中有若干内容, 例如 :nth-child() 伪类, 需要指示列表中的索引。 An+B 微语法对此很有用, 它允许作者轻松指示单个元素 或列表中以固定间隔出现的所有元素。

An+B 表示法定义一个整数 步长(A)和偏移量(B), 并表示列表中的第 An+B 个元素, 对于 n 的每个正整数或零值, 列表中的第一个元素的索引为 1(而不是 0)。

对于大于 0 的 A 和 B 值, 这实际上会将列表划分为每组 A 个元素 (最后一组包含余数), 并选择每组中的第 B 个元素。

An+B 表示法还接受 even 和 odd 关键字, 它们分别与 2n 和 2n+1 具有相同含义。

示例:

2n+0   /* 表示列表中的所有偶数序号元素 */
even   /* 相同 */
4n+1   /* 表示列表中的第 1、5、9、13 等个元素 */

A 和 B 的值可以为负数, 但只使用 An+B 的正数结果, 对于 n ≥ 0, 。

示例:

-1n+6   /* 表示列表中的前 6 个元素 */
-4n+10  /* 表示列表中的第 2、6 和 10 个元素 */

如果 A 和 B 都为 0, 则该伪类不表示列表中的任何元素。

6.1. 非正式语法说明

本节是非规范性的。

当 A 为 0 时,可以省略 An 部分 (除非 B 部分已经省略)。 当未包含 An 且 B 为非负数时, B 前面的 + 号(如果允许) 也可以省略。 在这种情况下,语法简化为只有 B。

示例:

0n+5   /* 表示列表中的第 5 个元素 */
5      /* 相同 */

当 A 为 1 或 -1 时, 可以从规则中省略 1。

示例:

因此,以下表示法等价:

1n+0   /* 表示列表中的所有元素 */
n+0    /* 相同 */
n      /* 相同 */

如果 B 为 0,则会选择每第 A 个元素。 在这种情况下, 可以省略 +B(或 -B)部分, 除非 A 部分已经省略。

示例:

2n+0   /* 表示列表中的每个偶数序号元素 */
2n     /* 相同 */

当 B 为负数时,其减号取代 + 号。

有效示例:

3n-6

无效示例:

3n + -6

当 An 和 B 部分都存在时,分隔它们的 + 或 - 两侧 都允许有空白。

带空白的有效示例:

3n + 1
+3n - 2
-n+ 6
+6

带空白的无效示例:

3 n
+ 2n
+ 2

6.2. <a-n-plus-b> 类型

An+B 表示法最初使用与 CSS 其余部分略有不同的标记器定义, 因此用 CSS 标记来表达时,其定义显得有些奇怪。 本节描述如何根据 CSS 标记识别 An+B 表示法 (从而为 CSS 语法用途定义 <a-n-plus-b> 类型), 以及如何解释 CSS 标记以获得 A 和 B 的值。

测试

<a-n-plus-b> 类型定义为 (使用值与单位规范中的值定义 语法) :

<a-n-plus-b> =
  odd | even |
  <integer> |

  <n-dimension> |
  '+'?† n |
  -n |

  <ndashdigit-dimension> |
  '+'?† <ndashdigit-ident> |
  <dashndashdigit-ident> |

  <n-dimension> <signed-integer> |
  '+'?† n <signed-integer> |
  -n <signed-integer> |

  <ndash-dimension> <signless-integer> |
  '+'?† n- <signless-integer> |
  -n- <signless-integer> |

  <n-dimension> ['+' | '-'] <signless-integer> |
  '+'?† n ['+' | '-'] <signless-integer> |
  -n ['+' | '-'] <signless-integer>

其中:

†:当加号 (+) 位于以 "n" 开头的 ident 前面时,如上面标记的情况, 两个标记之间不得有空白, 否则这些标记不匹配上述语法。 其他任意两个标记之间允许存在空白(并会被忽略)。

产生式的各分支解释如下:

odd
A 为 2,B 为 1。
even
A 为 2,B 为 0。
<integer>
A 为 0,B 为该整数的值。
<n-dimension>
'+'? n
-n
A 分别为该维度的值、1 或 -1。 B 为 0。
<ndashdigit-dimension>
'+'? <ndashdigit-ident>
A 分别为该维度的值或 1。 B 分别为该维度的单位或 ident 的值, 移除第一个代码点,并将剩余部分解释为十进制数。 B 为负数。
<dashndashdigit-ident>
A 为 -1。 B 为 ident 的值,其中移除前两个代码点 并将剩余部分解释为十进制数。 B 为负数。
<n-dimension> <signed-integer>
'+'? n <signed-integer>
-n <signed-integer>
A 分别为该维度的值、1 或 -1。 B 为该整数的值。
<ndash-dimension> <signless-integer>
'+'? n- <signless-integer>
-n- <signless-integer>
A 分别为该维度的值、1 或 -1。 B 为该整数值的相反数。
<n-dimension> ['+' | '-'] <signless-integer>
'+'? n ['+' | '-'] <signless-integer>
-n ['+' | '-'] <signless-integer>
A 分别为该维度的值、1 或 -1。 B 为该整数的值。 如果两者之间提供的是 '-',则 B 改为该 整数值的相反数。

7. 为规则和其他值定义语法

CSS 值第 4 级 § 2 值定义 语法定义了如何为属性和其他 CSS 语法构造指定语法。

测试

7.1. 定义块内容:<block-contents>、<declaration-list>、<qualified-rule-list>、<declaration-rule-list> 和 <rule-list> 产生式

CSS 解析器并不关心块的内容——它们都使用相同的 算法进行解析, 并且仅通过哪些构造有效来彼此区分。

编写规则语法时, <block-contents> 表示这种不区分内容的解析。 它只能作为块中的唯一值使用, 并表示不会隐式施加任何限制 来约束块中可以包含的内容。

随附的规范文本必须定义在此上下文中哪些内容有效、哪些无效。 如果任何声明有效, 并且是属性声明, 则必须定义它们是否与层叠交互; 如果交互,则必须定义其优先级 以及它们如何使用 !important。

然而,在许多情况下, 一个块无法有效包含给定类型的任何构造。 为了更明确地表示这些情况, 可以使用以下产生式

就解析而言,所有这些都与 <block-contents> 完全等价, 但随附的规范文本只需为 不会自动无效的类别定义有效性。

以下是各种产生式的一些示例:
例如,@font-face 的语法可以写为:
<@font-face> = @font-face { <declaration-list> }

然后随附的规范文本定义块中允许的有效描述符 。

@keyframes 的语法可以写为:

<@keyframes> = @keyframes { <qualified-rule-list> }
<keyframe-rule> = <keyframe-selector> { <declaration-list> }

然后随附的规范文本定义只有 <keyframe-rule> 才允许出现在 @keyframes 中, 并且 <keyframe-rule> 接受所有可动画的 CSS 属性, 以及 animation-timing-function 属性, 但它们不参与层叠。

7.2. 定义任意内容:<declaration-value> 和 <any-value> 产生式

在某些语法中, 允许语法接受任何合理的输入很有用, 然后手动对内容执行更具体的错误处理 (而不是简单地使构造无效, 因为语法不匹配通常会这样做)。

例如,自定义 属性允许任何合理的值, 因为它们可以包含其他 CSS 属性的任意片段, 或用于完全不属于现有 CSS 的内容。 再例如,媒体查询中的 <general-enclosed> 产生式 定义未来 MQ 语法所允许内容的边界, 并使用特殊逻辑来处理“未知”值。

为此,定义了两个额外的产生式:

<declaration-value> 产生式匹配由 一个或多个标记组成的任何序列, 只要该序列不包含 <bad-string-token>、 <bad-url-token>、 不匹配的 <)-token>、<]-token> 或 <}-token>, 或顶层 <semicolon-token> 标记,或值为 "!" 的 <delim-token> 标记。 它表示有效声明的值可以包含的全部内容。

<any-value> 产生式与 <declaration-value> 相同, 但还允许顶层 <semicolon-token> 标记 和值为 "!" 的 <delim-token> 标记。 它表示在任何上下文中有效 CSS 可以包含的全部内容。

8. CSS 样式表

要解析 CSS 样式表, 首先解析 样式表。 将所有所得的顶层限定规则解释为下文定义的样式规则。

如果任何样式规则无效, 或任何 at-rule 无法识别,或根据其语法或上下文无效, 则这是一个解析错误。 丢弃该规则。

8.1. 样式规则

样式规则是一个限定规则, 它将一个选择器列表 与一个属性声明列表 以及可能的一个嵌套规则列表相关联。 它们在 [CSS2] 中也称为 规则集。 CSS 层叠与继承 [CSS-CASCADE-3] 定义样式规则中的声明如何 参与层叠。

限定规则的前奏会被解析 为 <selector-list>。 如果返回失败, 则整个样式规则无效。

限定规则的块内容被解析为 <declaration-list>。 此块中的限定规则也是样式规则。 除非其他规范或本规范的未来级别另有定义, 该列表中的 at-rule 无效 并且必须被忽略。

注:[CSS-NESTING-1] 定义条件分组规则 和一些其他at-rule 允许出现在样式规则内部。

未知 CSS 属性的声明 或其值不匹配该属性定义语法的声明无效 并且必须被忽略。 样式规则内容的有效性不会影响样式规则本身的有效性。 除非另有规定,属性名称进行 ASCII 大小写不敏感匹配。

注:自定义属性 [CSS-VARIABLES] 的名称 区分大小写。

CSS 样式表顶层的限定规则是样式 规则。 其他上下文中的限定规则可能是,也可能不是样式规则, 具体由上下文定义。

例如,@media 规则 [CSS3-CONDITIONAL] 内的限定规则是 样式规则, 但 @keyframes 规则 [CSS3-ANIMATIONS] 内的限定规则不是。

8.2. At-rule

at-rule 是一个以 at-keyword 开始的规则, 因此可以将它与同一上下文中的样式 规则区分开来。

At-rule 用于:

At-rule 有多种形式,具体取决于特定规则及其用途, 但大体上分为两种: 语句 at-rule ,它们是以分号结束的较简单构造, 以及 块 at-rule ,它们以 {}-block 结束, 其中可以包含嵌套的限定规则、at-rule 或声明。

块 at-rule通常 包含一组 (通用或特定于 at-rule 的) at-rule、限定规则和/或描述符声明, 并受该 at-rule 定义的限制约束。 描述符类似于属性 (并使用相同语法声明), 但与特定类型的 at-rule 相关联, 而不是与树中的元素和框相关联。

8.3. @charset 规则

用于为样式表确定回退编码的算法 会在文件最开始的几个字节中查找特定字节序列, 其语法形式是名为 "@charset" 的at-rule。

测试

但是,并不存在实际名为 @charset 的at-rule。 当实际解析样式表时, 出现的任何 @charset 规则都必须被视为无法识别的规则, 因而在对样式表进行语法检查时作为无效规则丢弃。

注:在 CSS 2.1 中,@charset 是有效规则。 某些旧版规范可能仍会引用 @charset 规则, 并明确讨论其在样式表中的存在。

测试

9. 序列化

本规范中描述的标记器不会为注释生成标记, 也不会以其他方式保留它们。 实现可以保留注释内容及其在标记流中的位置。 如果这样做,这些保留的信息不得对解析步骤产生任何影响。

本规范不定义通常如何序列化 CSS, 而是将该任务留给 [CSSOM] 和各个特性规范。 特别是,注释和空白的序列化方式未定义。

序列化的唯一要求是它必须能够与解析“往返”, 即解析样式表必须产生与 解析、序列化并再次解析相同的数据结构, 连续的 <whitespace-token> 除外, 它们可以折叠为单个标记。

注:此例外之所以可行,是因为 CSS 语法始终将任意数量的空白解释为与单个空格相同。

为满足此要求:
ident 函数 url 错误 url - 数字 百分比 维度 CDC ( * %
ident ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
at-keyword ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
hash ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
维度 ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
# ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
- ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
数字 ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗
@ ✗ ✗ ✗ ✗ ✗ ✗
. ✗ ✗ ✗
+ ✗ ✗ ✗
/ ✗
测试

9.1. 序列化 <a-n-plus-b>

给定整数值 A 和 B,要序列化一个 <a-n-plus-b> 值:
  1. 如果 A 为零, 返回 B 的序列化。

  2. 否则,令 result 初始为空字符串。

  3. A 为 1

    将 "n" 附加到 result。

    A 为 -1

    将 "-n" 附加到 result。

    A 非零

    序列化 A 并将其附加到 result, 然后将 "n" 附加到 result。

  4. B 大于零

    将 "+" 附加到 result, 然后将 B 的序列化附加到 result。

    B 小于零

    将 B 的序列化附加到 result。

  5. 返回 result。

10. 隐私考虑

本规范未引入新的隐私问题。

11. 安全考虑

本规范提高了安全性,因为现在已为所有输入明确定义 CSS 解析。

对于白名单/过滤器等旧解析器,如果其解析方式与本规范不同, 它们在一定程度上是不安全的, 但先前的解析规范留下了许多浏览器会作不同解释的模糊边缘情况, , 因此这些过滤器本来就可能不安全, 而本规范不会使情况恶化。

12. 更改

本节是非规范性的。

12.1. 自 2021 年 12 月 24 日候选推荐标准草案以来的更改

进行了以下实质性更改:

12.2. 自 2019 年 8 月 16 日候选推荐标准以来的更改

进行了以下实质性更改:

进行了以下编辑性更改:

12.3. 自 2014 年 2 月 20 日候选推荐标准以来的更改

进行了以下实质性更改:

进行了以下编辑性更改:

评论处理结果 可在此查看。

12.4. 自 2013 年 11 月 5 日最终征求意见工作草案以来的更改

12.5. 自 2013 年 9 月 19 日工作草案以来的更改

12.6. 自 CSS 2.1 和选择器第 3 级以来的更改

注:本规范的目标是与现实相符; 相较 CSS2.1 的更改几乎总是因为 CSS 2.1 指定的内容与实际浏览器 行为不符, 或者遗漏了某些规定。 如果某些细节与浏览器不符, 请告诉我, 因为这几乎肯定不是有意为之。

从字节流解码方面的更改:

标记化更改:

解析更改:

An+B 相较选择器第 3 级 [SELECT] 的更改:

致谢

感谢以下人员提供反馈和贡献: Anne van Kesteren、 David Baron、 Elika J. Etemad (fantasai)、 Henri Sivonen、 Johannes Koch、 呂康豪 (Kang-Hao Lu)、 Marc O’Morain、 Raffaello Giulietti、 Simon Pieter、 Tyler Karaszewski、 以及 Zack Weinberg。

一致性

文档约定

一致性要求使用 描述性断言与 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-rule、属性、属性值、关键字 和其他语法构造视为无效(并按适当方式 忽略)。特别是,用户代理不得选择性地 忽略不支持的组件值并接受单个 多值属性声明中的受支持值:如果任何值被视为无效 (不支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有特性的实现

为了避免与未来稳定的 CSS 特性发生冲突, CSSWG 建议对 CSS 的实现遵循最佳实践,以处理 不稳定特性和专有扩展。

非实验性实现

规范达到候选推荐标准阶段后, 即可进行非实验性实现,实现者应该 发布其能够证明根据规范正确实现的任何 CR 级特性的 无前缀实现。

为了建立并维护 CSS 在各实现之间的互操作性, CSS 工作组要求非实验性 CSS 渲染器在发布任何 CSS 特性的无前缀实现之前, 向 W3C 提交实现报告(如有必要,还包括 该实现报告所使用的测试用例)。提交给 W3C 的测试用例 须由 CSS 工作组审查和修正。

有关提交测试用例和实现报告的更多信息 可在 CSS 工作组的网站上找到: https://www.w3.org/Style/CSS/Test/。 问题应发送至 public-css-testsuite@w3.org 邮件列表。

CR 退出标准

要使本规范进入提议推荐标准阶段, 每项特性必须至少有两个独立且可互操作的实现。 每项特性可以由不同的一组产品实现, 不要求所有特性都由 单个产品实现。就此标准而言,我们定义 以下术语:

独立
每个实现必须由 不同的主体开发,并且不得共享、重用或派生自 另一个符合条件的实现所使用的代码。与 本规范实现无关的代码部分 不受此要求约束。
可互操作
通过 官方 CSS 测试套件中的相应测试用例;或者,如果实现不是 Web 浏览器,则通过等效测试。测试中的每个相关测试 套件都应创建等效测试,如果这样的用户 代理(UA)将被用于声称互操作性。此外, 如果要使用这样的 UA 声称互操作性,则 必须有一个或多个其他 UA 也能通过这些 等效测试,并以相同方式用于 互操作性。等效测试必须公开 提供,以供同行评审。
实现
符合以下条件的用户代理:
  1. 实现本规范。
  2. 向公众开放。该实现可以 是正式发布的产品或其他公开可用的版本 (即 beta 版本、预览版或“nightly build”)。 非正式发布的产品版本必须已经实现 相关特性至少一个月,以 证明稳定性。
  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-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-COUNTER-STYLES-3]
Tab Atkins Jr.. CSS 计数器样式第 3 级。2021 年 7 月 27 日。CR。URL:https://www.w3.org/TR/css-counter-styles-3/
[CSS-FONTS-4]
Chris Lilley. CSS 字体模块第 4 级。2026 年 9 月 13 日。WD。URL:https://www.w3.org/TR/css-fonts-4/
[CSS-NESTING-1]
Tab Atkins Jr.. CSS 嵌套模块第 1 级。 2026 年 1 月 22 日。WD。URL:https://www.w3.org/TR/css-nesting-1/
[CSS-PAGE-3]
Elika Etemad. CSS 分页媒体模块第 3 级。 2023 年 9 月 14 日。WD。URL:https://www.w3.org/TR/css-page-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS 语法模块第 3 级。2021 年 12 月 24 日。CRD。URL:https://www.w3.org/TR/css-syntax-3/
[CSS-TYPED-OM-1]
Tab Atkins Jr.; François Remy. CSS Typed OM 第 1 级。2024 年 3 月 21 日。WD。URL:https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位 模块第 4 级。2024 年 3 月 12 日。WD。URL:https://www.w3.org/TR/css-values-4/
[CSS-VARIABLES]
Tab Atkins Jr.. 用于层叠变量的 CSS 自定义属性 模块第 1 级。2022 年 6 月 16 日。CR。URL:https://www.w3.org/TR/css-variables-1/
[CSS3-CONDITIONAL]
Chris Lilley; David Baron; Elika Etemad. CSS 条件规则模块第 3 级。2024 年 8 月 15 日。CRD。URL:https://www.w3.org/TR/css-conditional-3/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型 (CSSOM)。2021 年 8 月 26 日。WD。URL:https://www.w3.org/TR/cssom-1/
[ENCODING]
Anne van Kesteren. 编码标准。现行 标准。URL:https://encoding.spec.whatwg.org/
[HTML]
Ian Hickson. HTML。现行标准。URL:http://whatwg.org/html
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准。现行标准。URL:https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. 用于 RFC 中 表示要求级别的关键词。1997 年 3 月。当前最佳实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器第 4 级。2026 年 1 月 22 日。WD。URL:https://www.w3.org/TR/selectors-4/
[URL]
Anne van Kesteren. URL 标准。现行标准。 URL:https://url.spec.whatwg.org/

非规范性参考文献

[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS 颜色模块 第 4 级。2026 年 9 月 26 日。CRD。URL:https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; Una Kravets; Lea Verou. CSS 颜色模块 第 5 级。2026 年 9 月 13 日。WD。URL:https://www.w3.org/TR/css-color-5/
[CSS-FONTS-5]
Chris Lilley. CSS 字体模块第 5 级。2026 年 9 月 13 日。WD。URL:https://www.w3.org/TR/css-fonts-5/
[CSS-NAMESPACES-3]
Elika Etemad. CSS 命名空间模块第 3 级。2014 年 3 月 20 日。REC。URL:https://www.w3.org/TR/css-namespaces-3/
[CSS-TEXT-DECOR-3]
Elika Etemad; Koji Ishii. CSS 文本装饰模块 第 3 级。2022 年 5 月 5 日。CRD。URL:https://www.w3.org/TR/css-text-decor-3/
[CSS-TEXT-DECOR-4]
Elika Etemad; Koji Ishii. CSS 文本装饰模块 第 4 级。2022 年 5 月 4 日。WD。URL:https://www.w3.org/TR/css-text-decor-4/
[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS 变换模块第 1 级。2019 年 2 月 14 日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[CSS-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS 值 与单位模块第 5 级。2024 年 11 月 11 日。WD。URL:https://www.w3.org/TR/css-values-5/
[CSS2]
Bert Bos; et al. 层叠样式表第 2 级修订版 1(CSS 2.1)规范。2011 年 6 月 7 日。REC。URL:https://www.w3.org/TR/CSS2/
[CSS3-ANIMATIONS]
David Baron; et al. CSS 动画第 1 级。2023 年 3 月 2 日。WD。URL:https://www.w3.org/TR/css-animations-1/
[MEDIAQ]
Tab Atkins Jr.; Florian Rivoal. 媒体查询第 4 级。2026 年 2 月 19 日。CRD。URL:https://www.w3.org/TR/mediaqueries-4/
[MEDIAQUERIES-5]
Tab Atkins Jr.; et al. 媒体查询第 5 级。2026 年 2 月 19 日。WD。URL:https://www.w3.org/TR/mediaqueries-5/
[SELECT]
Tantek Çelik; et al. 选择器第 3 级。2018 年 11 月 6 日。REC。URL:https://www.w3.org/TR/selectors-3/