1. 介绍
本节不是规范性的。
本模块定义了CSS样式表的抽象语法和解析以及其他使用CSS语法的内容
(例如HTML style
属性)。
它定义了将Unicode 代码点流(换句话说,文本) 转换为CSS标记流的算法, 然后进一步转换为CSS对象 例如样式表、规则和声明。
1.1. 模块交互
本模块定义了CSS样式表的语法和解析。 它取代了在CSS 2.1中定义的词法分析器和语法。
2. CSS语法描述
本节不是规范性的。
CSS文档是一系列样式规则——
一个合格规则以前导开始,
然后有一个{}括起来的块,包含一系列声明。
前导的含义根据规则出现的上下文而异——
一个典型的规则可能看起来像这样:
p > a { color: blue; text-decoration: underline; }
在上面的规则中,"p > a
" 是选择器,
如果源文档是HTML,
将选择任何
a
元素,它们是
p
元素的子元素。
"color: blue
" 是一个声明,指定对于匹配选择器的元素,
它们的color
属性应具有值blue。
类似地,它们的text-decoration 属性应具有值underline。
At-rules 都是不同的,但它们有一个共同的基本结构。 它们以 "@" 代码点 开头,后跟它们的名称作为CSS关键字。 一些at-rules 是简单语句, 名称后跟更多的CSS值以指定其行为, 最后以分号结束。 其他是块; 它们可以在名称后有CSS值, 但它们以{}包围的块结束, 类似于合格规则。 甚至这些块的内容也特定于给定的at-rule: 有时它们包含一系列声明,如合格规则; 有时,它们可能包含附加块、at-rules或完全不同的结构。
以下是几个at-rules的示例, 说明它们可能包含的多样语法。
@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名称始终是 标识符序列, 必须以标识符起始代码点、两个连字符或一个连字符后跟一个标识符起始代码点开头, 然后可以包含零个或多个标识符代码点。 您可以包含任何代码点, 甚至是CSS语法中使用的代码点, 通过转义它。
选择器的语法在选择器规范中定义。 同样,各种CSS值的语法在值与单位规范中定义。 各个at-rules的特殊语法可以在定义它们的规范中找到。
2.1. 转义
本节不是规范性的。
任何Unicode 代码点都可以通过转义包含在标识符序列或引号字符串中。 CSS转义序列以反斜杠(\)开头,接下来是:
- 任何不是十六进制数字或换行符的Unicode 代码点。 转义序列将被替换为该代码点。
-
或一个到六个十六进制数字,
后跟一个可选的空格。
转义序列将被替换为其值由十六进制数字给出的Unicode 代码点。
这个可选的空格允许十六进制转义序列后面跟随“真实”的十六进制数字。
一个标识符序列的值为 "&B" 可以写成\26 B或\000026B。
转义序列后的“真实”空格必须加倍。
2.2. 错误处理
本节不是规范性的。
当CSS中发生错误时,
解析器尝试优雅地恢复,
仅丢弃最少量的内容
然后正常返回到解析中。
这是因为错误并不总是失误——
具体的错误恢复行为在解析器本身中详细说明, 但它足够简单,以至于简短的描述相当准确。
- 在样式表的“顶层”,
<at-keyword-token>开始一个at-rule。
其他任何东西开始一个合格规则,
并包含在规则的前导中。
这可能产生一个无效选择器,
但这不是CSS解析器的关注点——
最坏的情况是选择器将匹配不到任何内容。 - 一旦开始一个at-rule, 从解析器的角度来看,没有什么是无效的; 这都是at-rule的前导的一部分。 遇到一个<semicolon-token>立即结束at-rule, 而遇到一个左大括号<{-token>开始at-rule的主体。 at-rule向前匹配块(被()、{}或[]包围的内容) 直到找到一个不被其他任何东西匹配或不在另一个块内的右大括号<}-token>。 然后,at-rule的内容根据at-rule自身的语法进行解释。
- 合格规则类似, 只是分号不会结束它们; 相反,它们只是作为规则前导的一部分被接受。 当找到第一个{}块时, 内容始终被解释为声明列表。
- 在解释声明列表时, 任何地方的未知语法导致解析器丢弃它当前构建的任何声明, 并向前寻找直到找到一个分号(或块的结束)。 然后它重新开始,尝试再次解析一个声明。
- 如果样式表在任何规则、声明、函数、字符串等仍然开放时结束, 一切都会自动关闭。 这并不使它们无效, 尽管它们可能不完整 并因此在与其语法进行验证时被丢弃。
在每个结构(声明、样式规则、at-rule)被解析后, 用户代理会将其与预期的语法进行检查。 如果它不匹配语法, 则它是无效, 并被用户代理忽略, 用户代理将其视为不存在。
3. 词法分析和解析CSS
用户代理必须使用本规范中描述的解析规则 从text/css资源生成[CSSOM]树。 这些规则共同定义了所称的CSS解析器。
本规范定义了CSS文档的解析规则, 无论它们是否语法正确。 解析算法中的某些点被称为解析错误。 解析错误的错误处理是明确的: 用户代理在遇到此类问题时,必须按照下面描述的方式采取行动, 或者在遇到它们不希望应用下面描述的规则的第一个错误时中止处理。
合规检查工具必须在文档中存在一个或多个解析错误条件时 至少报告一个解析错误条件, 如果文档中不存在解析错误条件,则不得报告解析错误条件。 如果文档中存在多个解析错误条件, 合规检查工具可以报告多个解析错误条件。 合规检查工具不要求从解析错误中恢复, 但如果它们这样做, 则必须以与用户代理相同的方式恢复。
3.1. 解析模型概述
CSS解析过程的输入由Unicode代码点流组成, 该流经过词法分析阶段,然后是树构建阶段。 输出是一个CSSStyleSheet对象。
注意:不支持脚本的实现不必实际创建CSSOM CSSStyleSheet对象, 但在这种情况下,CSSOM树仍然作为其余规范的模型使用。
3.2. 输入字节流
在解析样式表时, 组成词法分析阶段输入的Unicode 代码点流可能最初会被用户代理视为字节流 (通常来自网络或本地文件系统)。 如果是这样,用户代理必须根据特定字符编码将这些字节解码为代码点。
代码点
流:
注意: 解码算法 优先考虑字节顺序标记(BOM), 仅在未找到时使用后备编码。
- 如果HTTP或等效协议为stylesheet提供了编码标签(例如通过Content-Type头的charset参数), 获取编码来自编码标签。 如果没有返回失败, 则返回它。
-
否则,检查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-8而声明是utf-16?
编码声明的字节拼写为“
@charset "…";
”以ASCII表示, 但UTF-16不是ASCII兼容的。 要么你输入的是完全无意义的内容(例如䁣桡牳整•utf-16be∻
), 以获得文档中的正确字节, 我们不想鼓励这样, 要么你的文档实际上是ASCII兼容编码, 而你的编码声明是错误的。无论哪种情况,默认使用UTF-8是一个不错的选择。
此外,这模仿了HTML的
<meta charset>
属性的行为。注意: 注意编码声明的语法 看起来像命名为at-rule的语法@charset, 但实际上并不存在这样的规则, 并且写法的规则要比正常情况下识别此类规则的规则要严格得多。 在CSS中可以做的许多事情会产生有效的@charset规则(如果存在), 例如使用多个空格、注释或单引号, 会导致编码声明无法被识别。 这种行为使编码声明尽可能简单, 从而最大限度地提高其被正确实现的可能性。
- 否则,如果引用文档提供了环境编码, 则返回该编码。
- 否则,返回
utf-8
。
尽管UTF-8是网络的默认编码, 并且许多较新的基于Web的文件格式假设或要求UTF-8编码, CSS在不确定哪种编码会胜出之前就已创建, 因此无法自动假定样式表为UTF-8。
样式表作者应以UTF-8编写他们的样式表,
并确保通过HTTP头(或等效方法)声明样式表的编码为UTF-8,
或引用文档声明其编码为UTF-8。
(在HTML中,通过将<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. 输入流的预处理
输入流由在解码输入字节流时推入的过滤的代码点组成。
4. 词法分析
要将一串代码点 input转换为一串CSS令牌,反复消费一个令牌 直到达到一个<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>、<whitespace-token>、<CDO-token>、<CDC-token>、 <colon-token>、<semicolon-token>、<comma-token>、<[-token>、 <]-token>、 <(-token>、 <)-token>、 <{-token>、 和<}-token>。
- <ident-token>、<function-token>、<at-keyword-token>、<hash-token>、<string-token>,以及<url-token>的值由零个或多个代码点组成。 此外,哈希令牌具有一个类型标志,设置为“id”或“unrestricted”。如果未另行设置,则类型标志默认为“unrestricted”。
- <delim-token>的值由一个单一的代码点组成。
- <number-token>、<percentage-token>,以及<dimension-token>具有数值。<number-token>和<dimension-token>另外还具有一个类型标志,设置为“integer”或“number”。如果未另行设置,则类型标志默认为“integer”。<dimension-token>还具有一个由一个或多个代码点组成的单位。
注意: 哈希令牌的类型标志用于选择器语法[SELECT]。 只有类型为“id”的哈希令牌才是有效的ID选择器。
4.1. 令牌铁路图
本节为非规范性内容。
本节以铁路图的形式呈现词法分析器的相关信息。 铁路图比显式解析器更紧凑,但通常比正则表达式更易读。
这些图是信息性和不完整的; 它们描述了“正确”令牌的语法, 但没有描述任何错误处理。 提供这些图只是为了更直观地理解每个令牌的语法。
名称如<foo-token>的图表示令牌。 其余是由其他图引用的产生式。
- 注释
-
- 换行
-
- 空格
-
- 十六进制数字
-
- 转义
-
- <whitespace-token>
-
- ws*
-
- <ident-token>
-
- <function-token>
-
- <at-keyword-token>
-
- <hash-token>
-
- <string-token>
-
- <url-token>
-
- <number-token>
-
- <dimension-token>
-
- <percentage-token>
-
- <CDO-token>
-
- <CDC-token>
-
4.2. 定义
本节定义了在标记化阶段使用的几个术语。
- 下一个输入码点
- 尚未被消耗的码点,位于输入流中。
- 当前输入码点
- 最近被消耗的码点。
- 重新消费当前输入码点
- 将当前输入码点推回到输入流的前面, 这样下次当你被指示消费下一个输入码点时, 它将重新消费当前输入码点。
- EOF码点
- 概念上的码点,表示输入流的结束。 每当输入流为空时, 下一个输入码点始终是EOF码点。
- 数字
- 在U+0030 数字零(0)和U+0039 数字九(9)之间(包含)。
- 十六进制数字
- 一个数字, 或一个码点,位于U+0041 拉丁大写字母A(A)和U+0046 拉丁大写字母F(F)之间(包含), 或一个码点,位于U+0061 拉丁小写字母A(a)和 U+0066 拉丁小写字母F(f)之间(包含)。
- 大写字母
- 一个码点,位于U+0041 拉丁大写字母A(A)和U+005A 拉丁大写字母Z(Z)之间(包含)。
- 小写字母
- 一个码点,位于U+0061 拉丁小写字母A(a)和U+007A 拉丁小写字母Z(z)之间(包含)。
- 字母
- 一个大写字母 或一个小写字母。
- 非ASCII码点
- 一个码点,其值大于或等于U+0080<control>。
- 标识符起始码点
- 一个字母, 一个非ASCII码点, 或U+005F 低线(_)。
- 标识符码点
- 一个标识符起始码点, 一个数字, 或U+002D 连字符(-)。
- 不可打印码点
- 一个码点,位于U+0000 NULL和U+0008 BACKSPACE之间(包含), 或U+000B 行制表符, 或一个码点,位于U+000E SHIFT OUT和U+001F 信息分隔符一之间(包含), 或U+007F 删除。
- 换行
- U+000A 换行符。 请注意,U+000D 回车符和U+000C 表单换行符不包含在此定义中, 因为在预处理过程中它们会被转换为U+000A 换行符。
- 空白字符
- 一个换行、U+0009 字符制表符或U+0020 空格。
- 最大允许码点
- Unicode定义的最大码点:U+10FFFF。
- 标识符序列
-
一系列具有与<ident-token>相同语法的码点。
注意: 在<at-keyword-token>中“@”后的部分, 在<hash-token>(带有“id”类型标志)中的“#”后的部分, 在<function-token>中的“(”之前的部分, 以及在<dimension-token>中的单位部分都属于标识符序列。
- 表示
-
一个表示是由
调用消费令牌算法
所消耗的输入流的子序列
生成的。
这对于依赖输入文本细微细节的几个算法是保留的,
简单的“重新序列化”令牌可能会干扰这些细节。
该表示仅由内部算法消耗, 并且从未直接暴露, 因此实际上不需要保留精确的文本; 等效的方法, 如将每个令牌与源文本中的偏移量相关联, 也足够满足需求。
注意: 特别是,表示保留了细节, 例如 .009 是以 .009 还是 9e-3 形式写成的, 以及字符是字面写出 还是作为CSS转义。 前者对于正确解析<urange> 生产是必要的; 后者基本上是令牌化抽象的意外泄漏, 但由于使实现更易于定义而被允许。
如果一个令牌是直接由算法生成的, 而不是通过本规范中的令牌化算法生成, 其表示为空字符串。
4.3. 词法分析算法
本节定义的算法将一系列码点转换为一系列 令牌。
4.3.1. 消耗一个令牌
本节描述如何从一系列码点中消耗一个令牌。它将返回一种类型的单个令牌。
消耗注释。
消耗下一个输入码点。
- 空白符
- 尽可能消耗多的空白符。 返回一个<whitespace-token>。
- U+0022 引号 (")
- 消耗一个字符串令牌并返回它。
- U+0023 井号 (#)
-
如果下一个输入码点是一个标识码点,或者下两个输入码点是有效转义,
那么:
- 创建一个<hash-token>。
- 如果下三个输入码点将开始一个标识序列, 将<hash-token>的类型标志设置为“id”。
- 消耗一个标识序列, 并将<hash-token>的值设置为返回的字符串。
- 返回<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 (-)
-
如果输入流 以数字开始, 重新消费当前输入代码点, 消费一个数字令牌,
并返回它。
否则, 如果 下两个输入代码点 是 U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), 消费它们 并返回一个 <CDC-token>。
否则, 如果输入流 以标识序列开始, 重新消费当前输入代码点, 消费一个标识类令牌, 并返回它。
否则, 返回一个 <delim-token>,其值设置为 当前输入代码点。
- U+002E FULL STOP (.)
-
如果输入流 以数字开始, 重新消费当前输入代码点, 消费一个数字令牌,
并返回它。
否则, 返回一个 <delim-token>,其值设置为 当前输入代码点。
- U+003A COLON (:)
- 返回一个 <colon-token>。
- U+003B SEMICOLON (;)
- 返回一个 <semicolon-token>。
- U+003C LESS-THAN SIGN (<)
-
如果 下三个输入代码点 是
U+0021 EXCLAMATION MARK
U+002D HYPHEN-MINUS
U+002D HYPHEN-MINUS
(!--),
消费它们
并返回一个 <CDO-token>。
否则, 返回一个 <delim-token>,其值设置为 当前输入代码点。
- U+0040 COMMERCIAL AT (@)
-
如果 下三个输入代码点 将开始一个标识序列, 消费一个标识序列,
创建一个 <at-keyword-token>,其值设置为返回值,
并返回它。
否则, 返回一个 <delim-token>,其值设置为 当前输入代码点。
- U+005B LEFT SQUARE BRACKET ([)
- 返回一个 <[-token>。
- U+005C REVERSE SOLIDUS (\)
-
如果输入流 以有效转义开始, 重新消费当前输入代码点, 消费一个标识类令牌,
并返回它。
否则, 这是一个 解析错误。 返回一个 <delim-token>,其值设置为 当前输入代码点。
- U+005D RIGHT SQUARE BRACKET (])
- 返回一个 <]-token>。
- U+007B LEFT CURLY BRACKET ({)
- 返回一个 <{-token>。
- U+007D RIGHT CURLY BRACKET (})
- 返回一个 <}-token>。
- 数字
- 重新消费当前输入代码点, 消费一个 数字令牌, 并返回它。
- 标识符起始 代码点
- 重新消费当前输入代码点, 消费一个标识类令牌, 并返回它。
- EOF
- 返回一个 <EOF-token>。
- 其他
- 返回一个 <delim-token>,其值设置为 当前 输入代码点。
4.3.2. 消费注释
本节描述如何从 代码点 的流中消费注释。 它不返回任何内容。
如果 下两个输入代码点 是 U+002F SOLIDUS (/) 后跟 U+002A ASTERISK (*), 消费它们 和所有随后的 代码点,直到并包括第一个 U+002A ASTERISK (*) 后跟 U+002F SOLIDUS (/), 或直到 EOF 代码点。 返回此步骤的开始。
如果前一段在消费一个 EOF 代码点时结束, 这是一个 解析错误。
不返回任何内容。
4.3.3. 消费数字令牌
本节描述如何从 代码点 的流中消费数字令牌。 它返回一个 <number-token>、<percentage-token>,或 <dimension-token>。
消费一个数字,让 number 为结果。
- 创建一个 <dimension-token>,与 number 具有相同的值和类型标志, 并且单位初始设置为空字符串。
- 消费一个标识序列。 将 <dimension-token> 的单位设置为返回值。
- 返回 <dimension-token>。
否则, 如果 下一个输入代码点 是 U+0025 PERCENTAGE SIGN (%), 消费它。 创建一个 <percentage-token>,其值与 number 相同, 并返回它。
否则, 创建一个 <number-token>,其值与类型标志与 number 相同, 并返回它。
4.3.4. 消费类似标识符的令牌
本节描述如何从代码点流中消费类似标识符的令牌。 它返回一个<ident-token>、<function-token>、<url-token>或<bad-url-token>。
消费标识符序列,并让string成为结果。
如果string的值与“url”存在ASCII 不区分大小写的匹配,且下一个输入代码点是U+0028 左括号 (, 则消费它。 当下两个输入代码点是空格时, 消费下一个输入代码点。 如果下一个或两个输入代码点是U+0022 引号 ("), U+0027 撇号 ('), 或空格后跟U+0022引号 (")或U+0027撇号 ('), 则创建一个<function-token>,其值设为string并返回。 否则,消费一个URL令牌, 并返回它。
否则,如果下一个输入代码点是U+0028 左括号 (, 则消费它。 创建一个<function-token>,其值设为string并返回。
否则, 创建一个<ident-token>,其值设为string并返回。
4.3.5. 消费字符串令牌
本节描述如何从代码点流中消费字符串令牌。 它返回一个<string-token>或<bad-string-token>。
此算法可以带有一个结束代码点, 用于标识结束字符串的代码点。 如果未指定结束代码点, 则使用当前输入代码点。
最初创建一个<string-token>,其值设为空字符串。
重复从流中消费下一个输入代码点:
- 结束代码点
- 返回<string-token>。
- EOF
- 这是一个解析错误。 返回<string-token>。
- 换行符
- 这是一个解析错误。 重新消费当前输入代码点, 创建一个<bad-string-token>并返回它。
- U+005C 反斜杠 (\)
-
如果下一个输入代码点是EOF,
则什么都不做。
否则,如果下一个输入代码点是换行符, 则消费它。
否则,(流以有效转义开始) 消费转义代码点并将返回的代码点附加到<string-token>的值中。
- 其他
- 将当前输入代码点附加到<string-token>的值中。
4.3.6. 消费 URL 令牌
本节描述了如何从一系列代码点中消费 URL 令牌。 它返回一个<url-token>或一个<bad-url-token>。
注意:该算法假设初始的 "url(" 已被消费。 该算法还假设它被调用以消费一个“未引用”的值, 如url(foo)。 一个引用的值,如url("foo"), 被解析为一个<function-token>。消费一个类似标识符的 令牌会自动处理这个区别; 否则,不应直接调用此算法。
- 最初创建一个<url-token>,其值设置为空字符串。
- 尽可能消费空白。
-
从流中重复消费下一个输入代码点:
- U+0029 右括号 ())
- 返回<url-token>。
- EOF
- 这是一个解析错误。 返回<url-token>。
- 空白
- 尽可能消费空白。 如果下一个输入代码点是U+0029右括号 ())或EOF, 消耗它并返回<url-token>(如果遇到EOF,这是一个解析错误); 否则,消费坏 URL 的剩余部分, 创建一个<bad-url-token>, 并返回它。
- U+0022 引号 (")
- U+0027 撇号 (')
- U+0028 左括号 (()
- 不可打印代码点
- U+0027 撇号 (')
- 这是一个解析错误。 消费坏 URL 的剩余部分, 创建一个<bad-url-token>, 并返回它。
- U+005C 反斜杠 (\)
-
如果流以有效转义开头,消费转义代码点并将返回的代码点附加到<url-token>的值中。
否则, 这是一个解析错误。 消费坏 URL 的剩余部分, 创建一个<bad-url-token>, 并返回它。
- 其他任何内容
- 将当前输入代码点附加到<url-token>的值中。
4.3.7. 消费转义代码点
本节描述了如何消费转义代码点。 它假设U+005C反斜杠(\)已经被消费, 且下一个输入代码点已经被验证为有效转义的一部分。 它将返回一个代码点。
消费下一个 输入代码点。
- 十六进制数字
- 尽可能消费十六进制数字,但不超过5个。 注意,这意味着总共消费了1-6个十六进制数字。 如果下一个输入代码点是空白,也要消费它。将十六进制数字视为一个十六进制数。如果这个数字为零,或者是一个代理,或者大于最大允许代码点,返回U+FFFD替换字符(�)。否则,返回值为该值的代码点。
- EOF
- 这是一个解析错误。返回U+FFFD替换字符(�)。
- 其他任何内容
- 返回当前输入代码点。
4.3.8. 检查两个代码点是否为有效的转义
本节描述了如何检查两个代码点是否为有效的转义。这里描述的算法可以显式调用两个代码点,或者可以直接调用输入流。在后一种情况下,相关的两个代码点是当前输入代码点和下一个输入代码点,顺序为此。
注意:该算法不会消费任何额外的代码点。
如果第一个代码点不是U+005C反斜杠(\),返回false。
否则,返回true。
4.3.9. 检查三个代码点是否会开始一个标识符序列
本节描述了如何检查三个代码点是否会开始一个标识符序列。 这里描述的算法可以显式调用三个代码点, 或者可以直接调用输入流。在后一种情况下,相关的三个代码点是当前输入代码点和接下来的两个输入代码点,顺序为此。
注意:该算法不会消费任何额外的代码点。
查看第一个代码点:
- U+002D 连字符
- 如果第二个代码点是一个标识符开始代码点或U+002D 连字符,或者第二个和第三个代码点 是一个有效的转义,返回true。否则,返回false。
- 标识符开始代码点
- 返回true。
- U+005C 反斜杠 (\)
- 如果第一个和第二个代码点 是一个有效的转义,返回true。否则,返回false。
- 其他任何内容
- 返回false。
4.3.10. 检查三个代码点是否会开始一个数字
本节描述了如何检查三个代码点是否会开始一个数字。 这里描述的算法可以显式调用三个代码点, 或者可以直接调用输入流。在后一种情况下,相关的三个代码点是当前输入代码点和接下来的两个输入代码点,顺序为此。
注意:该算法不会消费任何额外的代码点。
查看第一个代码点:
- U+002B 加号 (+)
- U+002D 连字符 (-)
- 如果第二个代码点是一个数字,返回true。
否则,如果第二个代码点是U+002E 句点 (.),且第三个代码点是一个数字,返回true。
否则,返回false。
- U+002E 句点 (.)
- 如果第二个代码点是一个数字,返回true。否则,返回false。
- 数字
- 返回true。
- 其他任何内容
- 返回false。
4.3.11. 消耗标识序列
本节描述了如何从一系列码点中消耗标识序列。 它返回一个字符串,该字符串包含 可以从流中相邻的码点开始形成的最大名称。
注意:此算法不会验证前几个码点 的有效性,这些是确保返回的码点 构成一个<ident-token>所必需的。 如果这是预期的使用,请确保流以标识序列开始 然后再调用此算法。
让result最初为空字符串。
重复消耗下一个输入码点:
- 标识码点
- 将码点附加到result。
- 流以有效转义开始
- 消耗转义码点。 将返回的码点附加到result。
- 其他情况
- 重新消耗当前输入码点。 返回result。
4.3.12. 消耗一个数字
本节描述了如何从一系列码点中消耗一个数字。 它返回一个数字value, 和一个type,其值为“integer”或“number”。
注意:此算法不会验证前几个码点 是否能够从流中获得数字。 确保流以数字开始后再调用 此算法。
按顺序执行以下步骤:
- 最初将type设置为“integer”。 让repr为空字符串。
- 如果下一个输入码点 是U+002B加号(+)或U+002D减号(-), 则消耗它并将其附加到repr。
- 当下一个输入码点是一个数字时, 消耗它并将其附加到repr。
- 如果下两个输入码点 是U+002E句号(.)后跟一个数字, 则:
- 如果下两个或三个输入码点 是U+0045拉丁大写字母E(E)或U+0065拉丁小写字母e(e), 可选跟随U+002D减号(-)或U+002B加号(+), 以及一个数字, 则:
- 将repr转换为数字, 并将value设置为返回的值。
- 返回value和type。
4.3.13. 将字符串转换为数字
本节描述了如何将字符串转换为数字。 它返回一个数字。
注意:此算法不会验证字符串是否仅包含数字。 确保字符串仅包含有效的CSS数字 然后再调用此算法。
将字符串分为七个部分, 从左到右排列:
- 一个 符号: 一个U+002B加号(+)或U+002D减号(-), 或空字符串。 如果符号为U+002D减号(-),让s为-1; 否则,让s为1。
- 一个 整数部分: 零个或多个数字。 如果至少有一个数字, 让i为将数字解释为基数为10的整数; 否则,让i为0。
- 一个 小数点: 一个U+002E句号(.), 或空字符串。
- 一个 小数部分: 零个或多个数字。 如果至少有一个数字, 让f为将数字解释为基数为10的整数, 让d为数字个数; 否则,让f和d为0。
- 一个 指数指示符: 一个U+0045拉丁大写字母E(E)或U+0065拉丁小写字母e(e), 或空字符串。
- 一个 指数符号: 一个U+002B加号(+)或U+002D减号(-), 或空字符串。 如果符号为U+002D减号(-),让t为-1; 否则,让t为1。
- 一个 指数: 零个或多个数字。 如果至少有一个数字, 让e为将数字解释为基数为10的整数; 否则,让e为0。
返回数字 s·(i + f·10-d)·10te
。
4.3.14. 消耗坏URL的残余部分
本节描述了如何消耗坏URL的残余部分, 从一系列码点中, “清理”在标记解析器意识到它正在处理一个<bad-url-token>而不是一个<url-token>后。 它不返回任何内容; 其唯一用途是消耗足够的输入流以达到一个恢复点, 在该点可以恢复正常的标记解析。
重复地从流中消耗下一个输入码点:
- U+0029右括号())
- EOF
- 返回。
- 输入流以有效转义开始
- 消耗转义码点。这允许遇到转义的右括号("\)")而不结束<bad-url-token>。 这在其他方面与“其他情况”相同。
- 其他情况
- 不做任何事。
5. 解析
解析阶段的输入是来自标记化阶段的标记流或列表。输出取决于解析器的调用方式,如本节后面列出的入口点所定义。解析器的输出可以包括 at-rules、合格规则和/或声明。
解析器的输出是根据 CSS 的基本语法构建的,而不考虑任何特定项的有效性。实现可以在各种解析器算法返回项时检查项的有效性,并在项根据实现的语法知识被认为无效时将算法视为返回无,或者可以按照规定构建完整的树,并在之后通过删除任何无效项进行“清理”。
可以出现在树中的项包括:
- at-rule
-
一个 at-rule
有一个名称、一个由组件值列表组成的前导和一个可选的简单 {} 块。
注意: 本规范对 at-rule 的块可能包含的内容没有限制。单个 at-rules 必须定义它们是否接受块,如果接受,如何解析它(最好使用本规范中定义的解析器算法或入口点)。
- 合格规则
- 一个合格规则有一个由组件值列表组成的前导和一个由简单 {} 块组成的块。
- 声明
-
概念上,声明是将属性或描述符名称与值关联的特定实例。在语法上,声明有一个名称,一个由组件值列表组成的值,以及一个最初未设置的 important 标志。
声明进一步分类为 属性声明 或 描述符 声明,前者设置 CSS 属性,并且在 合格规则 中最常见,后者设置 CSS 描述符, 仅在 at-rules 中出现。 (这种分类在语法级别并不发生;相反,它是声明出现位置的结果,并由定义给定规则的相应规范定义。)
- 组件值
- 组件值是 保留标记、函数 或 简单块 之一。
- 保留标记
-
任何由标记器产生的标记,除了 <function-token>s、<{-token>s、<(-token>s 和 <[-token>s。
注意: 上述非 保留标记 始终被消耗到更高层次的对象中,或者是函数,或者是简单块,因此在任何解析器输出中不会出现。
注意: 标记 <}-token>s、<)-token>s、<]-token>、<bad-string-token> 和 <bad-url-token> 始终是解析错误,但本规范通过保留它们在标记流中,允许其他规范(例如媒体查询)定义比仅丢弃整个声明或块更细粒度的错误处理。
- 函数
- 函数有一个名称和一个由组件值列表组成的值。
- 简单块
- {}-块
- []-块
- ()-块
- {}-块
- 一个简单块有一个相关标记(可以是 <[-token>、<(-token> 或 <{-token>)和一个由组件值列表组成的值。
5.1. 解析器铁路图
本节为非规范性内容。
本节以铁路图的形式展示了解析器的一个信息性视图。
这些图表是信息性和不完整的; 它们描述了“正确”样式表的语法, 但完全不描述错误处理。 它们仅用于帮助更直观地理解语法。
- 样式表
-
- 规则列表
-
- At规则
-
- 合格规则
-
- 声明列表
-
- 声明
-
- !重要
-
- 组件值
-
- {} 块
-
- () 块
-
- [] 块
-
- 函数块
-
5.2. 定义
- 当前输入 令牌
- 当前操作的令牌或组件 值,来自由标记器生成的令牌列表。
- 下一个输入令牌
- 在标记器生成的令牌列表中,当前输入令牌current input token之后的令牌或组件 值。 如果当前输入令牌后面没有令牌, 则下一个输入令牌 是一个<EOF-token>。
- <EOF-token>
- 表示令牌列表结束的概念令牌。 当令牌列表为空时, 下一个输入令牌 始终是一个<EOF-token>。
- 消耗下一个输入令牌
- 让当前输入令牌成为当前下一个输入令牌, 相应地调整下一个输入令牌。
- 重新消耗当前输入令牌
- 下次算法指示您消耗下一个输入令牌时, 请不要执行任何操作 (保持当前输入令牌不变)。
5.3. 解析器入口点
本节定义的算法从CSS令牌列表生成高级CSS对象。
要规范化为令牌流给定的input:
注意: 其他规范可以为其自身目的定义额外的入口点。
- "解析样式表" 旨在作为正常的解析器入口点,用于解析样式表。
- "解析规则列表" 旨在用于如@media等at-rule的内容。 它在处理<CDO-token>和<CDC-token>时,与"解析样式表"有所不同。
- "解析规则"
旨在由
CSSStyleSheet#insertRule
方法使用, 以及可能存在的类似功能, 将文本解析为单个规则。 - "解析声明" 用于@supports条件。 [CSS3-CONDITIONAL]
- "解析声明列表"
用于
style
属性的内容, 将文本解析为单个样式规则的内容。 - "解析组件值" 用于需要消耗单个值的内容, 如attr()的解析规则。
- "解析组件值列表"
用于表现属性的内容,
将文本解析为单个声明的值,
或用于解析独立选择器[SELECT]
或媒体查询列表[MEDIAQ],
如在选择器API或
media
HTML属性中。
5.3.1. 根据 CSS 语法解析某个内容
通常需要解析一个字符串或标记列表 以查看它是否符合某个 CSS 语法, 如果符合, 则根据语法进行解构。 本节提供了此类操作的通用钩子。 应该像 “将 foo 解析为 CSS <color>”, 或类似的方式调用。
该算法返回失败, 如果输入不符合提供的语法, 或根据语法解析输入的结果, 这是一个与提供的语法规范对应的不确定结构。 返回值只能通过规范文本进行交互, 其中表示的模糊性不是问题。 如果要在规范语言外部暴露, 使用结果的规范必须明确将其转换为明确定义的表示, 例如,通过调用 CSS 序列化算法 (如“序列化为 CSS <string> 值”).
注意:该算法, 以及 根据 CSS 语法解析逗号分隔的列表, 通常是其他规范想要调用的唯一解析算法。 其余解析算法主要用于 [CSSOM] 和相关的“显式构建 CSS 结构”案例。 如果你认为需要使用其他算法,请先咨询 CSSWG 的指导。
- 标准化 input, 并将 input 设置为结果。
- 从 input 中解析组件值的列表, 并让 result 成为返回值。
- 尝试将 result 与 grammar 进行匹配。 如果成功, 返回匹配的结果; 否则,返回失败。
5.3.2. 根据 CSS 语法解析逗号分隔的列表
虽然可以根据包含逗号的语法解析一个值, 如果值的 任何 部分解析失败, 整个值将无法解析, 并返回失败。
有时这正是所需的
(例如,在列表值的 CSS 属性中);
其他时候,
让值的每个逗号分隔的子部分分别解析更好,
处理成功解析的部分和未成功解析的部分
(通常忽略它们,
例如在
<img sizes>
中)。
该算法提供了一个简单的钩子来实现这一点。 它返回一个按“顶级”逗号分隔的值列表, 每个值要么是失败 (如果解析失败) 或解析的结果 (一个不确定的结构, 如 解析 算法中所述)。
- 标准化 input, 并将 input 设置为结果。
- 如果 input 仅包含 <whitespace-token>, 返回一个空的 列表。
- 从 input 中 解析逗号分隔的组件值列表, 并让 list 成为返回值。
- 对于 list 的每个 item, 用 grammar 对 item 进行 解析, 并替换 item。
- 返回 list。
5.3.3. 解析样式表
5.3.4. 解析规则列表
- 标准化 input, 并将 input 设置为结果。
- 从 input 中消费规则列表, 并将 top-level flag 设为未设置。
- 返回返回的列表。
5.3.5. 解析规则
- 标准化 input, 并将 input 设置为结果。
- 当 下一个输入令牌 从 input 是 <whitespace-token> 时,消费下一个输入令牌 从 input。
-
如果 下一个输入令牌
从 input 是 <EOF-token>,
返回语法错误。
否则,如果 下一个输入令牌 从 input 是 <at-keyword-token>,消费一个 at 规则 从 input, 并让 rule 为返回值。
否则,从 input 消费一个合格规则 并 让 rule 为返回值。 如果没有返回任何东西, 返回语法错误。
- 当 下一个输入令牌 从 input 是 <whitespace-token> 时,消费下一个输入令牌 从 input。
- 如果 下一个输入令牌 从 input 是 <EOF-token>, 返回 rule。 否则,返回语法错误。
5.3.6. 解析声明
注意: 与 "解析声明列表" 不同, 这仅解析一条声明,而不是 at 规则。
- 标准化 input, 并将 input 设置为结果。
- 当 下一个输入令牌 从 input 是 <whitespace-token> 时,消费下一个输入令牌。
- 如果 下一个输入令牌 从 input 不是 <ident-token>, 返回语法错误。
- 从 input 中消费一条声明。 如果返回了任何内容,返回它。 否则,返回语法错误。
5.3.7. 解析样式块内容
注意: 此算法解析 样式规则的内容, 需要允许 嵌套 的样式规则 和其他 at 规则。 如果您不需要嵌套的 样式规则, 例如在 @page 或在 @keyframes 子规则, 请使用 解析声明列表。
- 标准化 input, 并将 input 设置为结果。
- 从 input 中消费样式块内容, 并返回结果。
5.3.8. 解析声明列表
注意: 尽管名称如此, 但这实际上解析的是声明和 at 规则的混合列表, 如 CSS 2.1 对 @page 所做的那样。 意外的 at 规则(在给定上下文中可能全部都是)是无效的,将被消费者忽略。
注意: 此算法不处理嵌套的 样式规则。 如果您的使用需要这样,请使用 解析样式块内容。
- 标准化 input, 并将 input 设置为结果。
- 从 input 中消费声明列表, 并返回结果。
5.3.9. 解析组件值
- 标准化 input, 并将 input 设置为结果。
- 当 下一个输入令牌 从 input 是 <whitespace-token> 时,消费下一个输入令牌 从 input。
- 如果 下一个输入令牌 从 input 是 <EOF-token>, 返回语法错误。
- 从 input 中消费组件值 并让 value 为返回值。
- 当 下一个输入令牌 从 input 是 <whitespace-token> 时,消费下一个输入令牌 从 input。
- 如果 下一个输入令牌 从 input 是 <EOF-token>, 返回 value。 否则,返回语法错误。
5.3.10. 解析组件值列表
- 标准化 input, 并将 input 设置为结果。
- 重复 消费组件值 从 input 直到返回 <EOF-token>, 将返回的值(除了最后的 <EOF-token>)附加到列表中。 返回该列表。
5.3.11. 解析以逗号分隔的组件值列表
- 标准化 input, 并将 input 设置为结果。
- 让 list of cvls 为一个最初为空的组件值列表。
-
重复 消费组件值 从 input
直到返回 <EOF-token> 或 <comma-token>,
将返回的值(除了最后的 <EOF-token> 或 <comma-token>)附加到列表中。
将该列表附加到 list of cvls。
如果返回的是 <comma-token>, 重复此步骤。
- 返回 list of cvls。
5.4. 解析器算法
以下算法组成了解析器。 它们由上面的解析器入口点调用。
这些算法可以使用令牌或组件值列表进行调用。 (区别在于某些令牌在组件值列表中被替换为 函数 和 简单块。) 类似于在标记化阶段输入流返回的 EOF 代码点用于表示其为空, 此阶段的列表在请求下一个令牌但为空时必须返回 <EOF-token>。
可以使用特定列表调用算法, 在这种情况下它仅消费该列表 (当该列表耗尽时, 它开始返回 <EOF-token>)。 否则, 它隐式地与调用算法相同的列表调用。
5.4.1. 消费规则列表
为了 消费规则列表, 给定一个 顶级标志:
创建一个最初为空的规则列表。
重复消费 下一个输入令牌:
- <whitespace-token>
- 什么都不做。
- <EOF-token>
- 返回规则列表。
- <CDO-token>
- <CDC-token>
-
如果设置了 顶级标志,
什么都不做。
否则,重新消费当前输入令牌。 消费合格规则。 如果返回了任何内容, 将其附加到规则列表中。
- <at-keyword-token>
- 重新消费当前输入令牌。 消费 at-rule, 并将返回值附加到规则列表中。
- 其他任何情况
- 重新消费当前输入令牌。 消费 合格规则。 如果返回了任何内容, 将其附加到规则列表中。
5.4.2. 消费 at-rule
为了 消费 at-rule:
消费下一个输入令牌。 创建一个新的 at-rule, 其名称设置为 当前输入令牌 的值, 其前导初始设置为空的 列表, 其值初始设置为无。
重复消费 下一个输入令牌:
- <semicolon-token>
- 返回 at-rule。
- <EOF-token>
- 这是一个 解析错误。 返回 at-rule。
- <{-token>
- 消费简单块, 并将其分配给 at-rule 的块。 返回 at-rule。
- 简单块,其关联的令牌为 <{-token>
- 将块分配给 at-rule 的块。 返回 at-rule。
- 其他任何情况
- 重新消费当前输入令牌。 消费组件值。 将返回的值附加到 at-rule 的前导。
5.4.3. 消费合格规则
要 消费合格规则:
创建一个新的合格规则 其前导初始设置为空 列表, 其值初始设置为无。
重复消费 下一个输入令牌:
- <EOF-token>
- 这是一个 解析错误。 返回无。
- <{-token>
- 消费简单块并将其分配给合格规则的块。 返回合格规则。
- 简单块与关联的令牌 <{-token>
- 将块分配给合格规则的块。 返回合格规则。
- 其他
- 重新消费当前输入令牌. 消费组件值。 将返回的值附加到合格规则的前导。
5.4.4. 消费样式块的内容
要 消费样式块的内容:
创建一个初始为空的 声明列表 decls, 和一个初始为空的 规则列表 rules。
重复消费 下一个输入令牌:
- <whitespace-token>
- <semicolon-token>
- 无操作。
- <EOF-token>
- 扩展 decls与 rules, 然后返回 decls。
- <at-keyword-token>
- 重新消费当前输入令牌. 消费一个at规则, 并将结果附加到 rules。
- <ident-token>
- 初始化一个临时列表,初始填充 当前输入令牌。 当 下一个输入令牌 不是 <semicolon-token> 或 <EOF-token> 时,消费组件值并将其附加到临时列表。 从临时列表中消费声明。 如果返回任何内容, 附加到 decls。
- <delim-token> 值为 "&" (U+0026 AMPERSAND)
- 重新消费当前输入令牌. 消费合格规则。 如果返回任何内容, 附加到 rules。
- 其他
- 这是一个 解析错误。 重新消费当前输入令牌。 只要 下一个输入令牌 不是 <semicolon-token> 或 <EOF-token>, 消费组件值并丢弃返回值。
5.4.5. 消费声明列表
要消费声明列表:
创建一个初始为空的声明列表。
重复消费下一个输入标记:
- <whitespace-token>
- <semicolon-token>
- 不执行任何操作。
- <EOF-token>
- 返回声明列表。
- <at-keyword-token>
- 重新消费当前输入标记。 消费at规则。 将返回的规则附加到声明列表中。
- <ident-token>
- 初始化一个临时列表,初始填充为当前输入标记。 只要下一个输入标记不是<semicolon-token>或<EOF-token>,消费组件值并将其附加到临时列表中。 从临时列表中消费声明。 如果返回了任何内容, 将其附加到声明列表中。
- 其他任何情况
- 这是一个解析错误。 重新消费当前输入标记。 只要下一个输入标记不是<semicolon-token>或<EOF-token>,消费组件值并丢弃返回的值。
5.4.6. 消费声明
注意: 此算法假定下一个输入标记已经被检查为<ident-token>。
要消费声明:
消费下一个输入标记。 创建一个新声明 其名称设置为当前输入标记的值,值初始设置为空列表。
- 当下一个输入标记是<whitespace-token>时,消费下一个输入标记。
-
如果下一个输入标记是任何其他情况,而不是<colon-token>,
这是一解析错误。
返回无。
否则,消费下一个输入标记。
- 当下一个输入标记是<whitespace-token>时,消费下一个输入标记。
- 只要下一个输入标记是任何其他情况,而不是<EOF-token>,消费组件值并将其附加到声明的值中。
- 如果声明值中的最后两个非<whitespace-token>是一个<delim-token>,其值为"!" 后跟一个<ident-token>,其值为"important",则将声明设置为重要声明。
-
返回声明。
5.4.7. 消费组件值
要消费组件值:
如果当前输入标记是<{-token>,<[-token>,或<(-token>,消费简单块并返回它。
否则,如果当前输入标记是<function-token>,消费函数并返回它。
否则,返回当前输入标记。
5.4.8. 消费简单块
注意: 此算法假定当前输入标记已经被检查为一个<{-token>,<[-token>,或<(-token>。
要消费简单块:
结束标记是当前输入标记的镜像变体。 (例如,如果调用时是<[-token>,那么结束标记是<]-token>.)
创建一个简单块,其关联标记设置为当前输入标记,其值初始设置为空列表。
重复消费下一个输入标记并按如下方式处理:
- 结束标记
- 返回块。
- <EOF-token>
- 这是一个解析错误。 返回块。
- 其他任何情况
- 重新消费当前输入标记。 消费组件值并将其附加到块的值中。
注意: CSS在块中声明和合格规则之间存在不幸的语法模糊性,因此任何处理规则的“消费”算法最初将使用此更通用的算法,而不是更具体的消费声明列表或消费规则列表算法。 这些更具体的算法是在应用语法时调用的,具体取决于它是否包含<declaration-list>或<rule-list>/<stylesheet>。
5.4.9. 消耗一个函数
注意:该算法假设 当前输入令牌 已经被检查为 <function-token>。
要 消耗一个函数:
创建一个函数,其名称等于 当前输入令牌 的值,并将其值初始设置为空 列表。
重复消耗 下一个输入令牌 并按以下方式处理:
- <)-token>
- 返回函数。
- <EOF-token>
- 这是一种 解析错误。 返回函数。
- 其他任何情况
- 重新消费当前输入令牌。 消耗一个组件值 并将返回的值附加到函数的值上。
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 相同。
A 和 B 的值可以为负, 但仅使用 An+B 的正结果, 对于 n ≥ 0。
如果 A 和 B 均为 0, 该伪类表示列表中的无元素。
6.1. 非正式语法描述
本节为非规范性内容。
当 A 为 0 时,可以省略 An 部分 (除非 B 部分已经被省略)。 当 An 未包含且 B 为非负时, + 符号(在允许的情况下) 也可以省略。 在这种情况下,语法简化为仅 B。
当 A 为 1 或 -1 时,
规则中的 1
可以省略。
如果 B 为 0,则每 A 个元素被选中。 在这种情况下, +B(或 -B)部分可以省略, 除非 A 部分已经被省略。
当 B 为负时,其负号替代 + 符号。
在 + 或 - 的两侧允许有空格,以分隔 An 和 B 部分(当两者都存在时)。
6.2. <an+b>
类型
An+B 表示法最初是使用与 CSS 其余部分略有不同的标记解析器定义的, 结果在以 CSS 令牌表达时产生了一个有些奇怪的定义。 本节描述如何根据 CSS 令牌识别 An+B 表示法 (从而为 CSS 语法目的定义 <an+b> 类型), 以及如何解释 CSS 令牌以获得 A 和 B 的值。
<an+b> 类型的定义 (使用 值与单位规范中的值定义语法) 如下:
<an+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-dimension>
是一个 <dimension-token>,其类型标志设置为“integer”,单位与“n”的ASCII 不区分大小写 匹配<ndash-dimension>
是一个 <dimension-token>,其类型标志设置为“integer”,单位与“n-”的ASCII 不区分大小写 匹配<ndashdigit-dimension>
是一个 <dimension-token>,其类型标志设置为“integer”,单位与“n-*”的ASCII 不区分大小写 匹配,其中“*”是一系列一个或多个数字<ndashdigit-ident>
是一个 <ident-token>,其值是“n-*”的ASCII 不区分大小写 匹配,其中“*”是一系列一个或多个数字<dashndashdigit-ident>
是一个 <ident-token>,其值是“-n-*”的ASCII 不区分大小写 匹配,其中“*”是一系列一个或多个数字<integer>
是一个 <number-token>,其类型标志设置为“integer”<signed-integer>
是一个 <number-token>,其类型标志设置为“integer”,且其表示形式以“+”或“-”开头<signless-integer>
是一个 <number-token>,其类型标志设置为“integer”,且其表示形式以数字开头
†:当一个加号(+)位于以“n”开头的标识符前时,如上述标记的情况,两个标记之间必须没有空格,否则这些标记不符合上述语法。其他任何两个标记之间的空格是有效的(并被忽略)。
生成的条款解释如下:
- 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 为维度单位或标识符的值,去掉第一个代码点,其余部分被解释为十进制数字。 B 为负。
<dashndashdigit-ident>
- A 为 -1。 B 为标识符的值,去掉前两个代码点,其余部分被解释为十进制数字。 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. Unicode 范围微语法
一些构造,例如unicode-range描述符用于@font-face规则,需要一种方式来描述一个或多个unicode代码点。 <urange> 生成表示一个或多个unicode代码点的范围。
非正式地,<urange> 生成有三种形式:
- U+0001
- 定义一个包含单个代码点的范围,在这种情况下代码点为“1”。
- U+0001-00ff
- 定义代码点范围,在第一个和第二个值之间(含)定义范围,在这种情况下为“1”和“ff”(十进制的 255)之间的范围。
- U+00??
- 定义代码点范围,其中“?”字符的范围覆盖所有十六进制数字, 在这种情况下定义与值U+0000-00ff相同。
在每种形式中,每个十六进制数字允许最多 6 位数字(如果将“?”视为十六进制数字)。
7.1. <urange> 类型
<urange> 表示法最初被定义为 CSS 中的一个原始标记, 但它的使用非常少, 并与合法的 <ident-token> 以混乱的方式发生冲突。 本节描述如何根据现有的 CSS 标记识别 <urange> 表示法, 以及如何将其解释为 Unicode 码点的范围。
什么是混淆的冲突?
例如,在 CSS u + a { color: green;
} 中,
意图是一个 a
元素
跟随在 u
元素后面
应该被着色为绿色。
通常不需要在组合符和周围的选择器之间添加空格,
因此它 应该 等价于将其简化为
使用任何其他组合符,两个 CSS 片段应该是等价的, 但由于之前存在专门的 Unicode 范围标记, 因此简化代码的选择器部分现在包含一个 Unicode 范围, 而不是两个 idents 和一个组合符。 因此它未能匹配选择器语法, 规则被丢弃为无效。
(此示例来自于向 Firefox 报告的一个真实错误。)
注意: 此处描述的语法故意非常低级, 并面向实现者。 作者应该阅读前一节中的非正式语法描述, 因为它包含使用 <urange> 所需的所有信息, 而且实际上是可读的。
<urange> 类型的定义 (使用 值与单位规范中的值定义语法) 为:
<urange> = u '+' <ident-token> '?'* | u <dimension-token> '?'* | u <number-token> '?'* | u <number-token> <dimension-token> | u <number-token> <number-token> | u '+' '?'+
在这个生成中, 任何令牌之间都不能出现空格。
<urange> 生成表示一个或多个连续 的 Unicode 码点范围, 作为 开始值 和 结束值, 这些值是非负整数。 要将上述生成解释为一个范围, 按顺序执行以下步骤:
-
跳过第一个 u 令牌, 将所有生成中的令牌的 表示形式 连接在一起。 让这成为 text。
-
如果 text 的第一个字符是 U+002B 加号, 则消耗它。 否则, 这就是无效的 <urange>, 此算法必须退出。
-
从 text 中尽可能消耗多个 十六进制数字。 然后尽可能消耗多个 U+003F 问号 (?) 码点。 如果没有消耗到零 码点, 或消耗了超过六个 码点, 这就是无效的 <urange>, 此算法必须退出。
如果消耗了任何 U+003F 问号 (?) 码点,则:
-
将消耗的 码点 解释为十六进制数, 用 U+003F 问号 (?) 码点 替换为 U+0030 数字零 (0) 码点。 这就是 开始值。
-
将消耗的 码点 再次解释为十六进制数, 用 U+003F 问号 (?) 码点 替换为 U+0046 拉丁大写字母 F (F) 码点。 这就是 结束值。
-
退出此算法。
否则,将消耗的 码点 解释为 十六进制数。 这就是 开始值。
-
如果 text 中没有 码点, 则 结束值 与 开始值 相同。 退出此算法。
-
如果 text 中的下一个 码点 是 U+002D 连字符 (-), 则消耗它。 否则, 这就是无效的 <urange>, 此算法必须退出。
-
从 text 中尽可能消耗多个 十六进制数字。
如果没有消耗到零 十六进制数字, 或消耗了超过 6 十六进制数字, 这就是无效的 <urange>, 此算法必须退出。 如果 text 中还有任何 码点, 这就是无效的 <urange>, 此算法必须退出。
-
将消耗的 码点 解释为十六进制数。 这就是 结束值。
要确定 <urange> 代表什么码点:
注意: <urange> 的语法故意设定得比较宽泛; 其模式捕捉了非正式语法可以生成的所有可能令牌序列。 然而,它在其组成令牌之间不要求任何空格, 这使得在实际使用中相对安全。 即使是具有 <urange> 后接 <number> 或 <dimension> 的语法(如果作者指定了 <urange> 采用 ''u <number>'' 子句,可能看似模糊) 实际上是相当安全的, 因为作者需要故意用注释而不是空格分开 <urange> 和 <number>/<dimension>,才能造成歧义。 因此,虽然作者有可能写出以令人困惑的方式解析的内容, 但造成困惑所需的实际代码本身是复杂且罕见的。
8. 定义规则和其他值的语法
值 规范定义了如何为属性指定语法。 本节同样适用于规则。
就像在属性语法中一样,
表示法 <foo>
指的是“foo”语法术语,
假设在其他地方定义。
将 <foo>
替换为其定义将导致语义上相同的语法。
几种类型的令牌是逐字书写的,没有引号:
- <ident-token>s(例如
auto
、disc
等),其值直接书写。 - <at-keyword-token>s,写作 @
字符后跟令牌的值,例如
@media
。 - <function-token>s,写作函数
名称后跟 ( 字符,例如
translate(
。 - <colon-token>(写作
:
),<comma-token>(写作,
),<semicolon-token>(写作;
),<(-token>,<)-token>,<{-token>,和 <}-token>。
令牌匹配如果其值与语法中定义的值相匹配。 除非另有说明,所有匹配都是 ASCII 不区分大小写。
注意: 尽管可以通过 转义,
构造一个值以 (
结尾或以 @
开头的 <ident-token>,
但这样的令牌不是 <function-token> 或 <at-keyword-token>,并且不匹配相应的
语法定义。
<delim-token>s 以单引号括起来书写。
例如,包含 "+" 的 <delim-token>
被写作 '+'
。
同样,<[-token> 和 <]-token> 必须用
单引号书写,因为它们被语法本身用于分组子句。<whitespace-token> 在语法中从不指明;
<whitespace-token>s 允许
在任何两个令牌之前、之后和之间,
除非在文字定义中明确指定其他内容。
(例如,如果规则的前导是选择器,
空格是重要的。)
在定义函数或块时, 必须在语法中指定结束令牌, 但如果在最终的令牌流中不存在它, 它仍然匹配。
translateX( <translation-value> )
然而,样式表可能以未闭合的函数结束,如下所示:
.foo { transform: translate(50px
CSS 解析器将其解析为包含一个声明的样式规则, 其值是名为“translate”的函数。 这与上述语法匹配, 尽管结束令牌没有出现在令牌流中, 因为在解析器完成时, 结束令牌的存在已无法确定; 你所拥有的只是一个块和一个函数的事实。
8.1. 定义块内容:<declaration-list>, <rule-list>,和<stylesheet> 产生
CSS 解析器对块的内容不做具体区分,例如某些 at-rule 结束时的内容。用 token 定义块的通用语法并非易事,但有专门的、明确的算法用于解析此内容。
<style-block> 产生表示样式规则块的内容。它只能在语法中作为块内的唯一值使用,并表示该块的内容必须使用消耗样式块的内容算法进行解析。
<declaration-list> 产生表示声明列表。它只能在语法中作为块内的唯一值使用,并表示该块的内容必须使用消耗声明列表算法进行解析。
类似地,<rule-list> 产生表示规则列表,并只能在语法中作为块内的唯一值使用。它表示该块的内容必须使用消耗规则列表算法进行解析。
最后,<stylesheet> 产生表示规则列表。它与<rule-list>相同,但使用它的块默认接受所有不受特定上下文限制的规则。
允许声明 | 允许嵌套样式规则 | 允许任意合格规则 | 允许at-rule | 示例 | |
---|---|---|---|---|---|
<style-block> | ✓ | ✓ | ✗ | ✓ | 样式规则,@nest,嵌套条件组规则 |
<declaration-list> | ✓ | ✗ | ✗ | ✓ | @font,@counter-style,@page,@keyframes 子规则 |
<rule-list> | ✗ | ✗ | ✓ | ✓ | @keyframes,@font-feature-values |
<stylesheet> | ✗ | ✗ | ✓ | ✓ | 样式表,非嵌套条件组规则 |
如果某个上下文仅打算接受at-rule,例如在@font-features-values中, 实际上使用哪种产生并不重要,但<rule-list>因其更直白的名称而受到偏好。
@font-face { <declaration-list> }
这是规则语法的完整和充分定义。
作为另一个例子,@keyframes 规则更复杂, 其前言被解释为名称,并在其块中包含关键帧规则。 它们的语法是:
@keyframes <keyframes-name> { <rule-list> }
对于使用 <style-block> 或 <declaration-list> 的规则, 规则的规范必须定义哪些属性、描述符和/或 at-rules 在规则内部有效; 这可以简单地说为“@foo 规则接受本规范/章节中定义的属性/描述符”, 扩展规范可能简单地说“@foo 规则还额外接受以下属性/描述符”。 在块中发现的任何声明或 at-rules,如果未定义为有效, 必须从规则的值中删除。
在 <style-block> 或 <declaration-list>
内,!important
在任何描述符上自动无效。
如果规则接受属性,
规则的规范必须定义这些属性是否与级联相互作用,以及具有何种特定性。
如果它们不与级联相互作用,
则包含 !important
的属性自动无效;
否则,使用 !important
是有效的,
并使声明在 级联 的
目的下被视为重要。
请参阅[CSS-CASCADE-3]。
对于使用 <rule-list> 的规则, 规则的规范必须定义规则内部有效的规则类型, 与 <declaration-list> 相同, 并且未识别的规则必须类似地从规则的值中删除。
<keyframe-rule> = <keyframe-selector> { <declaration-list> }
关键帧规则必须进一步定义它们接受所有可动画的 CSS 属性作为声明, 以及 animation-timing-function 属性, 但它们不与级联相互作用。
对于使用 <stylesheet> 的规则, 默认情况下允许所有规则, 但规则的规范可以定义规则内部的哪些类型的规则是无效。
@media <media-query-list> { <stylesheet> }
它还定义了一个限制,即 <stylesheet> 不能包含 @media 规则, 如果它们出现,则会从外部规则的值中删除。
8.2. 定义任意内容: <declaration-value> 和 <any-value> 产生
在某些语法中, 接受语法中的任何合理输入是有用的, 并手动对内容进行更具体的错误处理 (而不是简单地使构造无效, 因为语法不匹配往往会导致这样的结果)。
例如, 自定义 属性 允许任何合理的值, 因为它们可以包含其他 CSS 属性的任意片段, 或用于与现有 CSS 完全无关的内容。 另一个例子是 <general-enclosed> 在媒体查询中的产生 定义了未来语法 MQs 将允许的范围, 并使用特殊逻辑来处理“未知”值。
为了帮助这一点,定义了两个附加的产生:
<declaration-value> 产生匹配 任意 序列 一个或多个标记, 只要序列不包含 <bad-string-token>, <bad-url-token>, 未匹配的 <)-token>, <]-token>,或 <}-token>, 或顶层 <semicolon-token> 标记或 <delim-token> 标记,其值为“!”。 它代表了一个有效声明可以具有的值的全部内容。
<any-value> 产生与 <declaration-value> 相同, 但还允许顶层 <semicolon-token> 标记 和 <delim-token> 标记,其值为“!”。 它代表了在任何上下文中有效的 CSS 的全部内容。
9. CSS 样式表
要 解析 CSS 样式表, 首先 解析一个 样式表。 将所有结果顶层的 合格规则 视为 样式规则,定义如下。
如果任何样式规则是 无效, 或任何 at-rule 未被识别或根据其语法或上下文无效, 则会发生 解析错误。 丢弃该规则。
9.1. 样式规则
一个 样式规则 是一个 合格规则,它将一个 选择器列表 与一系列属性声明以及可能的嵌套规则列表关联起来。 在 规则集 中,它们也被称为 [CSS2]。 CSS 层叠和继承 [CSS-CASCADE-3] 定义了样式规则内部的声明如何参与层叠。
合格规则的前导部分被 解析 为 <选择器列表>。 如果解析失败, 整个样式规则将被 标记为无效。
合格规则块的内容被解析为 样式块的 内容。 除非由其他规范或本规范的未来版本另行定义, 否则该列表中的 at-rules 是 无效 并且必须被忽略。
注意: [CSS-NESTING-1] 定义了 @nest 和 条件组规则 可以在 样式规则 内使用。
未知的 CSS 属性声明或其值不符合属性定义的语法的声明是 无效的,必须被忽略。 样式规则内容的有效性不影响样式规则本身的有效性。 除非另有说明,属性名称是 ASCII 不区分大小写。
注意: 自定义属性的名称 [CSS-VARIABLES] 是区分大小写的。
合格规则 在 CSS 样式表的 顶层是 样式规则。 其他上下文中的合格规则可能是也可能不是样式规则, 具体取决于上下文。
例如, 在 @media 规则 [CSS3-CONDITIONAL] 内的合格规则是样式规则, 但在 @keyframes 规则 [CSS3-ANIMATIONS] 内的合格规则则不是。
9.2. @规则
@规则 是以 @ 关键字开始的 规则, 因此可以与同一上下文中的 样式规则 区分开来。
@规则 用于:
@规则有多种形式,具体取决于特定规则及其目的, 大致上有两种类型:语句 @规则 是更简单的构造 以分号结束, 而 块 @规则 以 {}-块 结束,可以包含嵌套的 合格规则、@规则 或 声明。
块 @规则 通常包含一组 (通用或 @规则 特定的) @规则、合格规则 和/或 描述符声明 受限于 @规则 定义的限制。描述符 类似于 属性(并且 以相同的语法声明), 但与特定类型的 @规则 相关,而不是与树中的元素和盒子相关。
9.3. @charset 规则
用于 确定样式表的回退编码 的算法 查找文件开头的特定字节序列, 其语法形式为名为 "@charset" 的 @规则。
然而,并没有名为 @规则 的实际 @charset。 当样式表被实际解析时, 任何出现的 @charset 规则必须被视为未识别规则, 因此在语法检查时将被视为无效并被删除。
注意: 在 CSS 2.1 中, @charset 是一个有效的规则。 一些遗留规范可能仍然提到 @charset 规则,并明确讨论其在样式表中的存在。
10. 序列化
本规范中描述的标记器不会为注释生成标记, 或以任何方式保留它们。 实现可能保留注释的内容及其在标记流中的位置。 如果这样做,则此保留信息必须对解析步骤没有影响。
本规范并未定义如何一般性地序列化 CSS, 将此任务留给 [CSSOM] 和各个特性 规范。 特别是,注释和空白的序列化未定义。
序列化的唯一要求是它必须与解析“往返”, 即解析样式表必须生成与 解析、序列化和再次解析相同的数据结构, 除了连续的 <whitespace-token>, 可能会被合并为一个标记。
注意: 这个例外是因为 CSS 语法总是将任何数量的空白解释为等同于一个空格。
- 一个 <delim-token> 包含 U+005C 反斜杠 (\) 必须序列化为 U+005C 反斜杠 后跟一个 换行。 (标记器仅会发出这样的标记后跟一个 <whitespace-token>,该标记以换行符开始。)
- 一个 <hash-token> 的“无约束”类型标志可能不需要 像同一标记的“id”类型标志那样多的转义。
- 一个 <dimension-token> 的单位可能需要转义 以与科学计数法区分。
-
对于任何连续的标记对,
如果第一个标记出现在下表的行标题中,
并且第二个标记出现在列标题中,
并且在所选行和列的交集单元格中有 ✗,
则必须在它们之间序列化一个注释。
如果标记器保留注释, 则应使用保留的注释; 否则,必须插入一个空注释 (
/**/
)。 (保留的注释即使在以下表格不要求两个标记之间的注释时也可以重新插入。)行和列标题中的单个字符表示具有该值的 <delim-token>, 除了 "
(
", 代表 (-token。
标识符 | 函数 | 网址 | 错误网址 | - | 数字 | 百分比 | 维度 | CDC | ( | * | % | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
标识符 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ||
at-keyword | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
哈希 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
维度 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
# | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
- | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
数字 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
@ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ||||||
. | ✗ | ✗ | ✗ | |||||||||
+ | ✗ | ✗ | ✗ | |||||||||
/ | ✗ |
10.1. 序列化 <an+b>
-
如果 A 为零, 返回 B 的序列化。
-
否则,初始时让 result 为空 字符串。
-
- A 为
1
-
将 "n" 附加到 result。
- A 为
-1
-
将 "-n" 附加到 result。
- A 为非零
-
序列化 A 并附加到 result, 然后将 "n" 附加到 result。
- A 为
-
- B 大于零
-
将 "+" 附加到 result, 然后将 B 的序列化附加到 result。
- B 小于零
-
将 B 的序列化附加到 result。
-
返回 result。
11. 隐私和安全考虑
本规范没有引入新的隐私问题。
本规范提高了安全性,因为现在所有输入的 CSS 解析都被明确地定义。
就老解析器(如白名单/过滤器)与本规范的解析方式不同而言, 它们在某种程度上是不安全的, 但之前的解析规范留下了很多模糊的边缘情况,浏览器的解释也不尽相同, 所以那些过滤器可能已经不安全, 而本规范并没有恶化这种情况。
12. 变更
本节为非规范性。
12.1. 从2019年8月16日候选推荐的变化
进行了以下实质性更改:
-
添加了一个新的 § 5.3.2 根据CSS语法解析逗号分隔列表 算法。
-
添加了一个新的 § 5.3.7 解析样式块的内容 算法和相应的 <style-block> 生成,并定义了 样式规则 使用它。
-
将解析样式表与与Fetch相关的情节对齐。 (请参见提交。)
从input解析一个样式表 给定一个可选的url location :
- ...
- 创建一个新的样式表 , 其location设置为 location(如果未传递location则为null)。
- ...
进行了以下编辑性更改:
-
添加了§ 9.2 At-rules以提供at-rules、statement at-rules、block at-rules和 描述符的定义。 (5633)
-
始终使用ident序列,而不是有时使用“名称”这个术语。
-
明确命名了几个预标记化过程,并在解析入口点中明确引用它们 (而不是依赖于一个笼统的“在这些算法的开始做X”语句)。
-
向“在它们之间放置注释”表中添加了更多条目,以正确处理标识符现在可以以
--
开始的事实。 (6874)
12.2. 从2014年2月20日候选推荐的变化
进行了以下实质性更改:
-
移除了<unicode-range-token>,以创建<urange>生成。
-
包含字符串的url()函数现在被解析为正常的<function-token>。 包含“原始”URL的url()函数仍然特别解析为<url-token>。
-
修复了“消耗URL标记”算法中的一个错误, 该算法没有在尝试消耗字符串之前消耗开始字符串的引号字符。
-
修复了多个解析器算法中的错误 与当前/下一个输入标记和早期/晚期消耗有关。
-
修复了令牌化和解析算法中的几个错误。
-
更改了ident样式令牌的定义,以允许“--”以ident开始。 作为此的一部分,重新排列了消耗令牌的“-”步骤中的条款顺序,以便<CDC-token>被识别为这样,而不是变为-- <ident-token>。
-
当 A 为 1 或 -1 时,切勿序列化 <an+b> 中的数字。
-
定义所有令牌具有表示。
-
修复了检查两个代码点是否为有效转义中的小错误—— 一个
\
后跟EOF现在被正确报告为不是有效的转义。 样式表中的最后一个\
现在仅作为<delim-token>发出自身。 -
@charset不再是有效的CSS规则(现在只有一个编码声明,看起来像一个名为@charset的规则)
-
在解析过程中修剪声明值的开始/结束空格。
-
根据工作组决议移除了特定于选择器的令牌。
进行了以下编辑性更改:
-
“消耗字符串令牌”算法已更改,以允许在不指定显式结束令牌的情况下调用它, 这样它就会使用当前输入令牌。 该算法的三个调用站点已更改为使用该形式。
-
算法的轻微编辑结构调整。
-
添加了解析和解析以逗号分隔的组件值列表 API入口点。
-
移除了“代码点”和“代理代码点”,以使用Infra标准中的相同定义。
-
明确指出每个范围都是包含的。
-
向注释插入表添加了一列,以处理数字令牌出现在“%”分隔符令牌旁边的情况。
12.3. 从2013年11月5日最后呼叫工作草案的变更
- 序列化部分已被重写, 仅将“往返”要求定为规范, 并将如何实现它的细节移入备注中。 这些细节中的某些边缘情况已被修复。
- [编码]已添加到规范参考列表中。 在规范文本中已被引用, 只是没有列为规范参考。
-
在确定样式表的回退编码算法中,
将
@charset
字节序列限制为1024字节。 这与HTML对<meta charset>
的处理一致,并确保序列的大小有界。 这仅在编码标签中的前导或尾随空格时产生区别:@charset " (大量空格) utf-8";
12.4. 从2013年9月19日工作草案的变化
- 添加了环境编码的概念。 行为没有变化, 但一些定义应移至相关规范中。
12.5. 来自 CSS 2.1 和选择器级别 3 的变化
注意: 本规范的重点是匹配现实; 来自 CSS 2.1 的变化几乎总是因为 CSS 2.1 指定了一些与实际浏览器行为不符的内容, 或者留下一些未指定的内容。 如果某些细节与浏览器不匹配, 请告诉我, 因为这几乎肯定是无意的。
从字节流解码的变化:
- 仅在 ASCII 兼容的字节模式中检测 @charset 规则。
- 忽略指定 ASCII 不兼容编码的 @charset 规则, 因为这将导致规则本身无法正确解码。
- 引用 [编码] 而不是 IANA 字符编码注册表。
标记化变化:
- 在 CSS 源中,任何 U+0000 NULL 代码点 将被替换为 U+FFFD 替代字符。
- 任何评估为零的十六进制转义序列,例如 \0, 生成 U+FFFD 替代字符,而不是 U+0000 NULL。
- 非 ASCII 代码点 的定义已更改, 以与每个 ASCII 定义一致。 这影响 代码点 U+0080 到 U+009F, 这些现在是 标识代码点, 而不是 <delim-token>, 像其他 非 ASCII 代码点 一样。
- 标记化不再发出 COMMENT 或 BAD_COMMENT 令牌。 BAD_COMMENT 现在被视为普通令牌(而不是错误)。序列化 负责在需要分隔的令牌之间插入注释, 例如两个连续的 <ident-token>。
-
<unicode-range-token> 已被移除,
因为它的价值较低,有时还会造成实际伤害。
(例如,u+a { font-weight: bold; } 是无效选择器...)
相反,基于令牌模式添加了 <urange> 生产, 它在技术上比 2.1 允许的更加宽松 (任意数量的数字和 ? 字符), 但在任何实际使用中都不会造成影响。
- 在标记器中应用 EOF 错误处理规则 并发出正常的 <string-token> 和 <url-token> 而不是 BAD_STRING 或 BAD_URI 在 EOF 上。
- BAD_URI 令牌(现在是 <bad-url-token>)是“自包含的”。 换句话说,一旦标记器意识到它是在 <bad-url-token> 而不是 <url-token> 中, 它就向前查找以寻找结束 ), 忽略其他所有内容。 这种行为比将其视为 <function-token> 并关注打开的块要简单。 只有 WebKit 显示这种行为, 但似乎我们没有遇到任何兼容性错误。
- 添加了 <comma-token>。
- <number-token>、<percentage-token> 和 <dimension-token> 已更改, 将前面的 +/- 符号包含为其值的一部分 (而不是作为每次在其他规范中提到令牌时需要手动处理的单独 <delim-token>)。 唯一的结果是,注释不能再插入在符号和数字之间。
- 支持科学记数法用于数字/百分比/维度,以匹配 SVG, 根据工作组的决议。
- 对于 代理 的十六进制转义现在发出替代字符,而不是代理。 这允许实现安全地在内部使用 UTF-16。
解析变化:
- 任何声明列表现在还接受 at-rules,如 @page, 根据工作组的决议。 这会影响错误处理,即使尚未定义此类 at-rules: 一个 at-rule,无论有效与否,在没有 <semicolon-token> 的 {} 块结束, 允许下一个声明开始。
-
一些杂项“特殊”令牌的处理
(如在语法中的各种位置出现的不匹配的 <}-token>)
已被指定为至少一个浏览器显示的合理行为。
之前,含有这些令牌的样式表在这些位置根本不匹配样式表语法,
所以它们的处理完全未定义。
具体来说:
- [] 块、() 块和函数现在可以包含 {} 块、<at-keyword-token> 或 <semicolon-token>
- 合格规则前导现在可以包含分号
- 合格规则和 at-rule 前导现在可以包含 <at-keyword-token>
An+B 来自选择器级别 3 的变化 [SELECT]:
-
An+B 微语法现在已经根据 CSS 令牌正式定义,
而不是使用单独的标记器。
这导致了一些小差异:
- 在某些情况下,可以转义减号或数字 (当它们作为 <dimension-token> 或 <ident-token> 单位的一部分出现时)。
致谢
感谢以下人士的反馈和贡献: 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。