W3C

Selectors Level 3(选择器 级别 3)

W3C 推荐 2018年11月6日

此版本
https://w3org.cn/TR/2018/REC-selectors-3-20181106/
最新版本
https://w3org.cn/TR/selectors-3/
上一版本
https://w3org.cn/TR/2018/PR-selectors-3-20180911/
最新的 Selectors 版本
https://w3org.cn/TR/selectors/
编辑草案
https://drafts.csswg.org/selectors-3/
反馈
GitHub 上提交问题
编辑
Tantek Çelik(受邀专家)
Elika J. Etemad(受邀专家)
Daniel Glazman(Disruptive Innovations SARL)
Ian HicksonGoogle
Peter Linss(前编辑,Netscape/AOL
John Williams(前编辑,Quark, Inc.

请查阅 勘误表,了解自发布以来报告的任何错误或问题。


摘要

Selectors 是一类匹配树中元素的模式,因而构成用于在 XML 文档中选取节点的多种技术之一。Selectors 已针对 HTML 与 XML 进行了优化,并设计为可在性能关键的代码中使用。

CSS(层叠样式表)是一种描述 HTMLXML 文档在屏幕、纸张、语音等介质上呈现方式的语言。CSS 使用 Selectors 将样式属性绑定到文档中的元素。

本文档描述了已经在 CSS1 [CSS1]CSS2 [CSS21] 中存在的选择器,并进一步为 CSS3 与其他可能需要它们的语言引入新选择器。

Selectors 定义了如下函数

expression ∗ element → boolean

即,给定一个元素和一个选择器,本规范定义该元素是否匹配该选择器。

这些表达式同样可以用于,例如,在子树的所有元素上求值,以选取一组元素或从一组元素中选取单个元素。STTS(简易树转换表),一种用于转换 XML 树的语言,使用了此机制。[STTS3]

关于本文档

本节描述了本文件发布时的状态。其他文件可能会取代本文件。当前的 W3C 出版物列表和本技术报告的最新修订版可在 W3C 技术报告索引(https://w3org.cn/TR/)中找到。

此 W3C 推荐稿与 2018年9月11日的提议推荐稿 完全相同,只是状态信息和脚注已更新为 W3C 推荐稿。

本文件已由 W3C 会员、软件开发人员以及其他 W3C 小组和利害关系方审阅,并由总干事认可为 W3C 推荐标准。这是一个稳定的文档,可以用作参考材料或从另一个文档中引用。W3C 发布推荐标准的角色是引起对规范的关注并促进其广泛部署。这增强了 Web 的功能和互操作性。

本文档由 CSS 工作组 编写,作为 W3C 推荐稿

提议推荐稿是已被广泛审阅、准备实现的文档。W3C 鼓励所有人实现本规范,并在 2018年10月11日前通过 GitHub issue 提交意见。所有问题与评论均已 归档,并且还有 历史归档

本文件由在 W3C 专利政策下运作的小组编写。W3C 维护一份与该组交付成果相关的公开专利披露列表;该页面还包含披露专利的指南。任何对个人认为包含基本权利要求 (Essential Claim) 的专利有实际了解的个人,必须按照 W3C 专利政策第 6 节披露相关信息。

本文件受 2018 年 2 月 1 日 W3C 过程文档 的约束。

另有 测试套件实现报告 可供使用。

1. 简介

Selectors Level 1 与 Selectors Level 2 被定义为分别对应于 CSS1CSS2.1 规范中所定义的选择器功能的子集。

1.1. 依赖

本规范的某些特性专属于 CSS,或受 CSS 的特殊限制或规则约束。本文档中这些特性均以 CSS 2.1 为依据进行描述。[CSS21]

1.2. 术语

本规范的全部文本均为规范性内容,除示例、注释以及明确标记为非规范性的章节外。

额外的术语定义在 Definitions[CSS21])章节中。文档源代码与片段的示例使用 XML [XML10] 或 HTML [HTML401][HTML5] 语法给出。

1.3. 与 CSS2 的区别

本节是非规范性的。

CSS2 中的选择器与 Selectors 中的选择器的主要区别如下:

2. 选择器

本节为非规范性内容,仅对以下章节进行摘要。

选择器表示一种结构。该结构可用作条件(例如 CSS 规则中的条件),决定选择器在文档树中匹配哪些元素,也可用作对应于该结构的 HTML 或 XML 片段的扁平描述。

选择器的范围可以从简单的元素名称到丰富的上下文表示。

下表概括了选择器的语法

Pattern表示描述级别
* 任意元素通配选择器 2
EE 类型的元素类型选择器 1
E[foo]带有 “foo” 属性的 E 元素属性选择器 2
E[foo="bar"]其 “foo” 属性值恰好等于 “bar” 的 E 元素属性选择器 2
E[foo~="bar"]其 “foo” 属性值为由空格分隔的列表,其中有一项恰好等于 “bar” 的 E 元素属性选择器 2
E[foo^="bar"]其 “foo” 属性值以字符串 “bar” 开头的 E 元素属性选择器 3
E[foo$="bar"]其 “foo” 属性值以字符串 “bar” 结尾的 E 元素属性选择器 3
E[foo*="bar"]其 “foo” 属性值包含子串 “bar” 的 E 元素属性选择器 3
E[foo|="en"]其 “foo” 属性值为由连字符分隔的列表,且从左起首项为 “en” 的 E 元素属性选择器 2
E:root作为文档根的 E 元素结构伪类 3
E:nth-child(n)父元素的第 n 个子元素 E结构伪类 3
E:nth-last-child(n)父元素的倒数第 n 个子元素 E结构伪类 3
E:nth-of-type(n)同类型的第 n 个兄弟元素 E结构伪类 3
E:nth-last-of-type(n)同类型的倒数第 n 个兄弟元素 E结构伪类 3
E:first-child一个 E 元素,它是其父元素的第一个子元素结构伪类 2
E:last-child一个 E 元素,它是其父元素的最后一个子元素结构伪类 3
E:first-of-type一个 E 元素,它是其同类型元素中的第一个同胞结构伪类 3
E:last-of-type一个 E 元素,它是其同类型元素中的最后一个同胞结构伪类 3
E:only-child一个 E 元素,它是其父元素的唯一子元素结构伪类 3
E:only-of-type一个 E 元素,它是其同类型元素中的唯一同胞结构伪类 3
E:empty没有子节点(包括文本节点)的 E 元素结构伪类 3
E:link
E:visited
链接的源锚点为 E 元素,且目标尚未访问 (:link) 或已访问 (:visited)链接伪类 1
E:active
E:hover
E:focus
在特定用户操作期间的 E 元素用户操作伪类 1 和 2
E:target引用的 URI 的目标为 E 元素目标伪类 3
E:lang(fr)语言为 “fr” 的 E 类型元素(文档语言规定了语言的确定方式):lang() 伪类 2
E:enabled
E:disabled
启用或禁用的用户界面元素 EUI 元素状态伪类 3
E:checked 一个被选中的用户界面元素 E(已勾选)(例如单选按钮或复选框)UI 元素状态伪类 3
E::first-lineE 元素的第一行格式化文本::first-line 伪元素 1
E::first-letterE 元素的第一个格式化字母::first-letter 伪元素 1
E::before在 E 元素之前生成的内容::before 伪元素 2
E::after在 E 元素之后生成的内容::after 伪元素 2
E.warningclass 为 “warning” 的 E 元素(文档语言规定了类的确定方式)类选择器 1
E#myidID 等于 “myid” 的 E 元素。ID 选择器 1
E:not(s)不匹配简单选择器 s 的 E 元素否定伪类 3
E F作为 E 元素后代的 F 元素后代组合器 1
E > F作为 E 元素子代的 F 元素子代组合器 2
E + F紧跟在 E 元素后的 F 元素相邻同级组合符 2
E ~ F在 E 元素后的 F 元素后续同级组合符 3

3. 大小写敏感性

所有选择器语法在 ASCII 范围内均不区分大小写(即 [a‑z] 与 [A‑Z] 等价),除非是超出 Selectors 控制的部分。文档语言中元素名称、属性名称以及属性值的大小写敏感性取决于文档语言本身。例如,在 HTML 中元素名称不区分大小写,而在 XML 中则区分。命名空间前缀的大小写敏感性定义于 [CSS3NAMESPACE]

4. 选择器语法

A selector 是由一个或多个 simple selectors 序列 通过 组合符 分隔形成的链。一个 pseudo-element 可以附加在选择器最后的 simple selectors 序列之后。

A sequence of simple selectors 是一串未被 组合符 分开的 simple selectors,它始终以 type selectoruniversal selector 开头,序列中不允许出现其他 type selector 或 universal selector。

A simple selector 可以是 type selectoruniversal selectorattribute selectorclass selectorID selectorpseudo‑class

组合符 包括:空白、 “大于号” (U+003E, >)、 “加号” (U+002B, +) 与 “波浪号” (U+007E, ~)。空白可以出现在组合符与其两侧的 simple selector 之间。空白仅可由 “空格” (U+0020)、“制表符” (U+0009)、“换行” (U+000A)、“回车” (U+000D) 与 “换页符” (U+000C) 组成。其它类似空格的字符(如 “em‑space” (U+2003) 与 “ideographic space” (U+3000))永不属于空白。

由选择器表示的文档树元素称为 selector 的主体。由单一 simple selectors 序列构成的选择器表示满足该序列要求的任何元素。向序列前追加其他 simple selectors 序列与组合符会施加额外的匹配约束,因而选择器的主体始终是其最后一个 simple selectors 序列所代表元素的子集。

空的选择器(即不含任何 simple selectors 序列且不含 pseudo‑element)是 无效选择器

Selectors 中的字符可使用反斜杠进行转义,转义规则与 CSS 中的 相同[CSS21]

某些选择器支持命名空间前缀。命名空间前缀的 声明方式 应由使用 Selectors 的语言自行规定。若该语言未规定命名空间前缀声明机制,则视为没有前缀被声明。在 CSS 中,命名空间前缀通过 @namespace 规则声明。[CSS3NAMESPACE]

5. 选择器组

用逗号分隔的选择器列表表示所有列表中各个选择器所选元素的并集。(逗号为 U+002C。)例如,在 CSS 中当多个选择器共享相同声明时,可将它们组合成逗号分隔的列表。逗号前后均可出现空白。

CSS 示例

在本例中,我们将三个具有相同声明的规则压缩为一个。因此,

h1 { font-family: sans-serif }
h2 { font-family: sans-serif }
h3 { font-family: sans-serif }

等同于

h1, h2, h3 { font-family: sans-serif }

警告:此示例中的等价性成立是因为所有选择器都是有效的。若其中任意一个选择器无效,则整个选择器组皆无效,导致对所有三个标题元素的规则失效;而在前一种情况,仅有那条无效的单独标题规则会失效。

无效的 CSS 示例

h1 { font-family: sans-serif }
h2..foo { font-family: sans-serif }
h3 { font-family: sans-serif }

并不等同于

h1, h2..foo, h3 { font-family: sans-serif }

因为上面的选择器 (h1, h2..foo, h3) 完全无效,整个样式规则被丢弃。(如果选择器未被组合,则仅 h2..foo 的规则被丢弃。)

6. 简单选择器

6.1. 类型选择器

A type selector 是使用 CSS 合格名 语法书写的文档语言元素类型名称 [CSS3NAMESPACE]。type selector 表示文档树中该元素类型的实例。

示例

以下选择器表示文档树中的 h1 元素:

h1

6.1.1. 类型选择器与命名空间

type selector 允许可选的命名空间组件:先前已 声明 的命名空间前缀可以写在元素名称前,并用命名空间分隔符 “竖线” (U+007C, |) 与元素名称分隔。(参见 [XML-NAMES] 了解 XML 中命名空间的用法。)

可以将命名空间组件留空(即在命名空间分隔符前不写前缀),以指示该选择器只匹配没有命名空间的元素。

星号(*)可用作命名空间前缀,表示该选择器匹配任意命名空间中的元素(包括没有命名空间的元素)。

没有命名空间组件的元素类型选择器(即没有命名空间分隔符)在默认未声明 默认命名空间 时,等价于匹配所有命名空间的元素(等同于 “*|”)。若已在样式表中声明默认命名空间,则此类选择器仅匹配默认命名空间中的元素。

在选择器中使用了未提前 声明 的命名空间前缀的 type selector 为 无效 选择器。

在支持命名空间的客户端中,元素类型选择器的名称部分(命名空间分隔符后的部分,如有)只会与元素 局部部分 进行匹配。

总结

ns|E
namespace ns 中名称为 E 的元素
*|E
任意命名空间(包括没有命名空间)中名称为 E 的元素
|E
没有命名空间且名称为 E 的元素
E
如果未声明 默认命名空间,这等价于 *|E;否则等价于 ns|E(其中 ns 为默认命名空间)。

CSS 示例

@namespace foo url(http://www.example.com);
 foo|h1 { color: blue }  /* first rule */
 foo|* { color: yellow } /* second rule */
 |h1 { color: red }      /* ...*/
 *|h1 { color: green }
 h1 { color: green }

第一条规则(不计 @namespace at‑rule)只匹配位于 “http://www.example.com” 命名空间中的 h1 元素。

第二条规则匹配该命名空间中的所有元素。

第三条规则只匹配没有命名空间的 h1 元素。

第四条规则匹配任意命名空间中的 h1 元素(包括没有命名空间的情况)。

由于未定义默认命名空间,最后一条规则等价于第四条规则。

6.2. 通配选择器

The universal selector,写作带星号(*,U+002A)作为局部名称的 CSS 合格名 [CSS3NAMESPACE],表示任意元素类型的合格名。若未为选择器指定默认命名空间,它匹配文档树中任意命名空间(包括无命名空间)的单个元素;若已指定默认命名空间,请参见下文的 通配选择器与命名空间

如果由 *(即不带命名空间前缀)表示的通配选择器不是 simple selectors 序列 的唯一组成部分,或其后紧跟 pseudo‑element,则可以省略 *,其存在性被默认为。

示例

注意:建议不要省略 *,因为这会增加类似 div :first-childdiv:first-child 之间的混淆。此时 div *:first-child 更易读。

6.2.1. 通配选择器与命名空间

通配选择器允许可选的命名空间组件,使用方式如下:

ns|*
命名空间 ns 中的所有元素
*|*
所有元素
|*
没有命名空间的所有元素
*
如果未指定默认命名空间,则等价于 *|*;否则等价于 ns|*(其中 ns 为默认命名空间)。

包含未提前 声明 的命名空间前缀的通配选择器为 无效 选择器。

6.3. 属性选择器

Selectors 允许表示元素的属性。当选择器用作匹配表达式时,属性选择器必须在元素拥有与之相匹配的属性时视为匹配。

6.3.1. 属性存在与取值选择器

CSS2 引入了四种属性选择器:

[att]
表示拥有 att 属性的元素,无论该属性值为何。
[att=val]
表示拥有 att 属性且属性值恰好为 “val” 的元素。
[att~=val]
表示拥有 att 属性且属性值为以空白分隔的单词列表,其中至少有一个单词恰好为 “val”。如果 “val” 包含空白,则永不匹配;如果 “val” 为空字符串,也永不匹配。
[att|=val]
表示拥有 att 属性且属性值要么恰好为 “val”,要么以 “val-”(U+002D)开头的元素。此用法主要用于语言子代码匹配(如 HTML 中 a 元素的 hreflang 属性),参见 BCP 47 ([BCP47]) 或其后续规范。关于 lang(或 xml:lang)的语言子代码匹配,请参见 :lang 伪类

属性值必须是 CSS 标识符字符串[CSS21] 选择器中属性名与属性值的大小写敏感性取决于文档语言。

示例

以下属性选择器匹配文档树中携带 title 属性的 h1 元素(属性值不作要求):

h1[title]

在下列示例中,选择器匹配拥有 class 属性且属性值恰好为 “example” 的 span 元素:

span[class="example"]

可以使用多个属性选择器来表示同一元素的多个属性,或同一属性的多个条件。下面的选择器匹配 span 元素,其 hello 属性值恰好为 “Cleveland”,且 goodbye 属性值恰好为 “Columbus”。

span[hello="Cleveland"][goodbye="Columbus"]

下面的 CSS 规则演示了 “=” 与 “~=” 的区别。第一个选择器会匹配例如 rel 属性值为 “copyright copyleft copyeditor” 的 a 元素;第二个选择器则仅匹配 href 属性精确等于 “https://w3org.cn/” 的 a 元素。

a[rel~="copyright"] { ... }
a[href="https://w3org.cn/"] { ... }

以下选择器匹配 hreflang 属性恰好为 “fr” 的 a 元素。

a[hreflang=fr]

以下选择器匹配 hreflang 属性值以 “en” 开头的 a 元素,包括 “en”、 “en‑US” 以及 “en‑scouse”。

a[hreflang|="en"]

以下选择器匹配 DIALOGUE 元素,只要其 character 属性拥有两种不同的取值之一。

DIALOGUE[character=romeo]
DIALOGUE[character=juliet]

6.3.2. 子串匹配属性选择器

另外提供了三种属性选择器,用于匹配属性值中的子串。

[att^=val]
匹配拥有 att 属性且属性值以前缀 “val” 开头的元素。如果 “val” 为空字符串,则该选择器不匹配任何元素。
[att$=val]
匹配拥有 att 属性且属性值以后缀 “val” 结尾的元素。如果 “val” 为空字符串,则该选择器不匹配任何元素。
[att*=val]
匹配拥有 att 属性且属性值中至少包含一次子串 “val” 的元素。如果 “val” 为空字符串,则该选择器不匹配任何元素。

属性值必须是 CSS 标识符字符串[CSS21] 选择器中属性名的大小写敏感性取决于文档语言。

示例

以下选择器匹配一个引用图像的 HTML object 元素。

object[type^="image/"]

以下选择器匹配 href 属性值以 “.html” 结尾的 HTML 超链接 a

a[href$=".html"]

以下选择器匹配 title 属性值包含子串 “hello” 的 HTML 段落元素。

p[title*="hello"]

6.3.3. 属性选择器与命名空间

属性选择器中的属性名使用 CSS 合格名 表示:先前已 声明 的命名空间前缀可以写在属性名前,并用 “竖线” (|) 分隔。依据 XML 命名空间建议,默认命名空间不适用于属性,因此不含命名空间组件的属性选择器仅匹配没有命名空间的属性(等价于 “|attr”)。星号可用作命名空间前缀,表示匹配所有属性名,不考虑属性的命名空间。

属性名包含未提前 声明 的命名空间前缀的属性选择器为 无效 选择器。

CSS 示例

@namespace foo "http://www.example.com";
[foo|att=val] { color: blue }
[*|att] { color: yellow }
[|att] { color: green }
[att] { color: green }

第一条规则仅匹配位于 “http://www.example.com” 命名空间且属性值为 “val” 的 att 属性。

第二条规则匹配属性 att 位于任意命名空间(包括无命名空间)的元素。

最后两条规则等价,仅匹配属性不在任何命名空间中的 att 属性。

6.3.4. DTD 中的默认属性值

属性选择器表示文档树中属性的取值。文档树的构建方式不在 Selectors 范畴。某些文档格式在 DTD 或其他位置可定义默认属性值,但仅当这些默认属性出现在文档树中时才会被属性选择器选中。Selectors 应设计为在默认值是否出现在文档树中均能正常工作。

例如,XML UA 可以(但 不必)读取 DTD 的 “外部子集”,但 必须 在文档的 “内部子集” 中查找默认属性值。(参见 [XML10] 关于子集的定义。)根据不同的 UA,DTD 外部子集中的默认属性值可能会或可能不会出现在文档树中。

能够识别 XML 命名空间的 UA 可以(但不必)利用该命名空间信息将默认属性值视为已存在于文档中。(例如,XHTML UA 并不必须使用其内建的 XHTML DTD 知识。参见 [XML-NAMES] 了解 XML 1.0 中的命名空间细节。)

注意:通常实现会忽略外部子集。这对应于 XML 规格中非验证处理器的行为。

示例

设有元素 EXAMPLE,其属性 radix 的默认值为 “decimal”。对应的 DTD 片段可能是:

<!ATTLIST EXAMPLE radix (decimal,octal) "decimal">

如果样式表包含规则

EXAMPLE[radix=decimal] { /*... default property settings ...*/ }
EXAMPLE[radix=octal]   { /*... other settings...*/ }

若未显式设置 radix 属性,则第一条规则可能不匹配(因为属性是默认值),为覆盖所有情况,需要去掉针对默认值的属性选择器。

EXAMPLE                { /*... default property settings ...*/ }
EXAMPLE[radix=octal]   { /*... other settings...*/ }

在下面的例子中,选择器 EXAMPLE[radix=octal] 的特异性高于仅使用类型选择器的规则,因而第二条规则的样式声明会覆盖第一条规则中对 radix 为 “octal” 的元素的声明。必须确保仅针对默认情况的属性声明在非默认情况的样式规则中被覆盖。

6.4. 类选择器

在 HTML 中,作者可以使用 “句点” 记号(亦称 “点号”,U+002E,.)来代替 ~= 记号,以表示 class 属性。因此,对 HTML 而言,div.valuediv[class~=value] 含义相同。属性值必须紧随句点(.)后面。

如果 UA 拥有针对特定命名空间的知识,能够判断哪个属性是对应命名空间的 “class” 属性,则在 XML 文档中也可以使用句点(.)记号进行选择。例如,SVG 1.1 [SVG11] 说明了 SVG class 属性的用法,MathML [MATHML3] 同样描述了 MathML class 属性。

CSS 示例

我们可以如下为所有 class~="pastoral" 的元素分配样式信息:

*.pastoral { color: green }  /* all elements with class~=pastoral */

或者只写

.pastoral { color: green }  /* all elements with class~=pastoral */

下面的规则仅为 class~="pastoral" 的 H1 元素分配样式:

H1.pastoral { color: green }  /* H1 elements with class~=pastoral */

依据这些规则,下面第一个 H1 实例将不呈现绿色文本,而第二个会呈现。

<H1>Not green</H1>
<H1 class="pastoral">Very green</H1>

以下规则匹配任意 P 元素,只要其 class 属性的空白分隔列表同时包含 pastoralmarine

p.pastoral.marine { color: green }

class="pastoral blue aqua marine" 时该规则匹配;但对 class="pastoral blue" 则不匹配。

注意:由于 CSS 赋予 “class” 属性极大的表现力,作者可能会设想创建一种几乎不带任何表现的 “文档语言”(例如 HTML 中的 DIVSPAN),并通过 “class” 属性来分配样式信息。应避免此类做法,因为文档语言的结构元素往往已有公认且被接受的意义,而作者自定义的类名未必如此。

注意: 如果元素具有多个 class 属性,则在搜索类时必须将它们的值用空格连接在一起。到目前为止工作组并未知晓任何实现会出现此情况,因此此行为在本规范中明确为非规范性。

6.5. ID 选择器

文档语言可能包含声明为 ID 类型的属性。ID 类型属性的特殊之处在于,在符合规范的文档中,任何两个此类属性的值都不能相同,无论携带它们的元素是什么类型;不论文档语言为何,ID 类型属性都可用来唯一标识其所在的元素。HTML 中所有 ID 属性均叫作 “id”;XML 应用程序可以使用不同的属性名来表示 ID,但同样的限制仍然适用。

文档语言的 ID 类型属性允许作者为文档树中的某个元素实例分配一个标识符。ID 选择器包含一个 “井号”(U+0023,#),紧跟其后的是 ID 值,该值必须是一个 CSS 标识符。ID 选择器表示具有与该 ID 选择器中标识符相匹配的标识符的元素实例。

Selectors 并未规定用户代理如何获知元素的 ID 类型属性。用户代理可以例如读取文档的 DTD、将信息硬编码,或询问用户。

示例

下面的 ID 选择器表示一个 h1 元素,其 ID 类型属性的值为 “chapter1”。

h1#chapter1

下面的 ID 选择器表示任意元素,其 ID 类型属性的值为 “chapter1”。

#chapter1

下面的选择器表示任意元素,其 ID 类型属性的值为 “z98y”。

*#z98y

注意:在 XML 1.0 [XML10] 中,哪一个属性包含元素的 ID 信息存放在 DTD 或模式中。解析 XML 时,用户代理并不总是读取 DTD,因此可能不知晓元素的 ID(虽然用户代理可能拥有特定命名空间的知识,从而能够确定该命名空间的 ID 属性)。如果样式表作者知道或怀疑用户代理可能不知道元素的 ID,应该改用普通属性选择器:[name=p371] 而不是 #p371

如果一个元素拥有多个 ID 属性,则所有这些属性在 ID 选择器的语义下都必须被视为该元素的 ID。这种情况可能是通过 xml:id、DOM、XML DTD 以及特定命名空间的知识混合而成的。

6.6. 伪类

伪类概念被引入,以便基于文档树之外的信息或无法用其他简单选择器表达的信息进行选择。

伪类始终由一个 “冒号” (:) 加上伪类名称组成,名称后可选地带有用圆括号括起的值。

伪类可以出现在选择器中所有由简单选择器组成的序列中。伪类可出现在简单选择器序列的任意位置,位于首个类型选择器或通用选择器(可能被省略)之后。伪类名称不区分大小写。有些伪类互斥,而另一些可以同时应用于同一元素。伪类可能是动态的——即元素在用户与文档交互时可能获得或失去某个伪类。

6.6.1. 动态伪类

动态伪类依据元素除名称、属性或内容之外的特征对其进行分类,原则上这些特征无法从文档树中推断。

动态伪类不会出现在文档源码或文档树中。

用户代理通常会以不同的方式呈现未访问过的链接与已访问过的链接。Selectors 提供了伪类 :link:visited 用以区分它们。

在经过一定时间后,用户代理可能会将已访问的链接恢复为(未访问的)‘:link’ 状态。

这两种状态是互斥的。

示例

下面的选择器表示带有类 external 且已经被访问的链接。

a.external:visited

注意:样式表作者可能会滥用 :link 与 :visited 伪类来在未经用户同意的情况下判断用户访问了哪些站点。

因此,用户代理可能将所有链接都视为未访问链接,或采取其他措施在保持用户隐私的同时以不同方式渲染已访问和未访问的链接。

6.6.1.2. 用户动作伪类::hover、:active 与 :focus

交互式用户代理有时会根据用户动作改变渲染。Selectors 为选择用户正在交互的元素提供了三种伪类。

文档语言或实现可能对哪些元素能够变为 :active 或获得 :focus 设置特定限制。

这些伪类并不互斥。一个元素可以同时匹配多个伪类。

Selectors 并未规定处于 ‘:active’ 或 ‘:hover’ 状态的元素的父元素是否也处于相同状态。

注意:如果 ‘:hover’ 状态是因为其子元素被指向设备指向而产生的,则该状态可能会应用于并未直接位于指向设备下方的元素。

示例

a:link    /* unvisited links */
a:visited /* visited links */
a:hover   /* user hovers */
a:active  /* active links */

一个组合动态伪类的示例

a:focus
a:focus:hover

最后的选择器匹配同时拥有伪类 :focus 与伪类 :hover 的 a 元素。

注意:一个元素既可以是 ‘:visited’ 又可以是 ‘:active’(或者 ‘:link’ 与 ‘:active’)。

6.6.2. 目标伪类 :target

一些 URI 指向资源内部的某个位置。此类 URI 以 “井号” (#) 结尾,后跟锚点标识符(也称片段标识符)。

带有片段标识符的 URI 链接到文档中的特定元素,即目标元素。例如,下面的 URI 指向 HTML 文档中名为 section_2 的锚点。

http://example.com/html/top.html#section_2

目标元素可以用伪类 :target 表示。如果文档的 URI 没有片段标识符,则文档没有目标元素。

示例

p.note:target

该选择器表示类为 notep 元素,它是引用 URI 的目标元素。

CSS 示例

这里使用 :target 伪类将目标元素设为红色,并在其前面插入一张图片(如果有的话)。

*:target { color : red }
*:target::before { content : url(target.png) }

6.6.3. 语言伪类 :lang

如果文档语言规定了如何确定元素的人类语言,就可以编写基于语言的选择器。例如,HTML [HTML401] 中,语言由 lang 属性决定,并可能辅以 meta 元素或协议(如 HTTP 头)中的信息。XML 使用 xml:lang 属性,其他文档语言也可能有各自的语言确定方法。

伪类 :lang(C) 表示语言为 C 的元素。元素是否匹配 :lang() 选择器,仅依据该元素的语言值(若必要则规范化为 BCP 47 语法)是否等于标识符 C,或以 C 开头后紧跟 “-”(U+002D)。对 C 与元素语言值的匹配在 ASCII 范围内不区分大小写。标识符 C 本身不必是有效的语言名称。

C 必须是有效的 CSS 标识符 [CSS21],且不能为空。(否则选择器无效。)

注意:建议文档和协议使用 BCP 47 [BCP47] 或其后继的代码来指示语言,对于基于 XML 的文档则使用 “xml:lang” 属性 [XML10]。参见 “FAQ:两字母或三字母语言码”。

示例

下面的两个选择器表示使用比利时法语或德语的 HTML 文档。接下来的两个选择器表示在任意元素中使用比利时法语或德语的 q 引用。

html:lang(fr-be)
html:lang(de)
:lang(fr-be) > q
:lang(de) > q

伪类 :lang(C) 与 ‘|=’ 运算符的区别在于,‘|=’ 仅对元素的特定属性进行比较,而 :lang(C) 使用用户代理对文档语义的了解来进行比较。

在此 HTML 示例中,只有 BODY 匹配 [lang|=fr](因为它有 LANG 属性),但 BODYP 都匹配 :lang(fr)(因为两者都是法语)。P 不匹配 [lang|=fr],因为它没有 LANG 属性。

<body lang=fr>
  <p>Je suis français.</p>
</body>

6.6.4. UI 元素状态伪类

6.6.4.1. :enabled 与 :disabled 伪类

The :enabled 伪类表示处于启用状态的用户界面元素;此类元素对应有一个禁用状态。

相反,:disabled 伪类表示处于禁用状态的用户界面元素;此类元素对应有一个启用状态。

何为启用状态、禁用状态以及用户界面元素取决于语言。在典型文档中,大多数元素既非 :enabled 也非 :disabled

注意:可能影响用户与某个界面元素交互能力的 CSS 属性并不决定该元素是否匹配 :enabled:disabled;例如 displayvisibility 对元素的启用/禁用状态没有影响。

6.6.4.2. :checked 伪类

单选框和复选框元素可以被用户切换。某些菜单项在用户选择时会呈现 “已检查” 状态。当这些元素被切换为 “开” 时,:checked 伪类生效。虽然 :checked 伪类本质上是动态的,可随用户动作改变,但它也可以基于文档中语义属性的存在而适用于所有媒体。例如,:checked 伪类最初会匹配拥有 HTML4 selectedchecked 属性的元素(见 HTML4 第 17.2.1 节),但用户可以将这些元素切换为 “关闭”,此时 :checked 将不再匹配。

6.6.4.3. :indeterminate 伪类

注意:单选框和复选框元素可以被用户切换,但有时会处于不确定状态,即既不是已检查也不是未检查。这可能是由于元素属性或 DOM 操作导致的。

本规范的未来版本可能会引入 :indeterminate 伪类,以匹配此类不确定状态的元素。

6.6.5. 结构伪类

Selectors 引入了 结构性伪类 的概念,以便基于文档树中存在但无法用其他简单选择器或组合符表示的额外信息进行选择。

在计算元素在其兄弟列表中的位置时,不会计入独立文本和其他非元素节点;索引从 1 开始计数。

6.6.5.1. :root 伪类

:root 伪类表示文档的根元素。在 HTML 4 中,这始终是 HTML 元素。

6.6.5.2. :nth-child() 伪类

:nth-child(an+b) 伪类表示在文档树中,其前面(之前)有 an+b-1 个兄弟的元素,n 可以为任意正整数或零。该元素不一定必须有父元素。对于正数 ab,这相当于把子元素划分为每组 a 个(最后一组可能为余数),并选取每组的第 b 个。例如,这可用于为表格的每隔一行着色,或在四行循环中交替段落文字颜色。ab 必须为整数(可以为正、负或零)。第一个子元素的索引为 1。

此外,:nth-child() 还能接受 ‘odd’ 与 ‘even’ 作为参数。‘odd’ 等价于 2n+1,‘even’ 等价于 2n

:nth-child() 的参数必须符合下方语法,其中 INTEGER 匹配标记 [0-9]+,其余标记化规则见第 10.2 节的词法扫描器。

nth
  : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? |
         ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*
  ;

示例

tr:nth-child(2n+1) /* represents every odd row of an HTML table */
tr:nth-child(odd)  /* same */
tr:nth-child(2n+0) /* represents every even row of an HTML table */
tr:nth-child(even) /* same */

/* Alternate paragraph colours in CSS */
p:nth-child(4n+1) { color: navy; }
p:nth-child(4n+2) { color: green; }
p:nth-child(4n+3) { color: maroon; }
p:nth-child(4n+4) { color: purple; }

b 前带负号时,表达式中的 “+” 必须去掉(实际上被 “-” 替代,表示 b 为负数)。

示例

:nth-child(10n-1)  /* represents the 9th, 19th, 29th, etc, element */
:nth-child(10n+9)  /* Same */
:nth-child(10n+-1) /* Syntactically invalid, and would be ignored */

a=0 时,可以省略 an 部分(除非已经省略了 b 部分)。若省略了 anb 为非负数,则可以省去 b 前的 “+”。此时语法简化为 :nth-child(b)

示例

foo:nth-child(0n+5)   /* represents an element foo that is the 5th child
                         of its parent element */
foo:nth-child(5)      /* same */

a=1 或 a=‑1 时,可省略规则中的 “1”。

示例

因此以下选择器是等价的:

bar:nth-child(1n+0)   /* represents all bar elements, specificity (0,1,1) */
bar:nth-child(n+0)    /* same */
bar:nth-child(n)      /* same */
bar                   /* same but lower specificity (0,0,1) */

如果 b=0,则每第 a 个元素都会被选中。在这种情况下,+b(或‑b)可以省略,除非已省略了 a 部分。

示例

tr:nth-child(2n+0) /* represents every even row of an HTML table */
tr:nth-child(2n) /* same */

在 “(” 与 “)” 之间、以及在分隔 anb 的 “+” 或 “‑” 两侧,均可以出现空白字符。

带空格的有效示例

:nth-child( 3n + 1 )
:nth-child( +3n - 2 )
:nth-child( -n+ 6)
:nth-child( +6 )

带空格的无效示例

:nth-child(3 n)
:nth-child(+ 2n)
:nth-child(+ 2)

如果 ab 同时为零,则该伪类不匹配文档树中的任何元素。

a 可以为负数,但仅当 an+b 为正(n≥0)时,才能对应文档树中的元素。

示例

html|tr:nth-child(-n+6)  /* represents the 6 first rows of XHTML tables */
6.6.5.3. :nth-last-child() 伪类

:nth-last-child(an+b) 伪类表示在文档树中,其后(之后)有 an+b-1 个兄弟的元素,n 为任意正整数或零。该元素不必有父元素。其参数语法同 :nth-child()。同样接受 ‘even’ 与 ‘odd’ 作为参数。

示例

tr:nth-last-child(-n+2)    /* represents the two last rows of an HTML table */

foo:nth-last-child(odd)    /* represents all odd foo elements in their parent element,
                              counting from the last one */
6.6.5.4. :nth-of-type() 伪类

:nth-of-type(an+b) 伪类表示在文档树中,其前(之前)有 an+b-1 个拥有相同展开元素名的兄弟,n 为任意零或正整数。该元素不必有父元素。其参数语法同 :nth-child(),并接受 ‘even’ 与 ‘odd’。

CSS 示例

这让作者能够交替浮动图像的位置。

img:nth-of-type(2n+1) { float: right; }
img:nth-of-type(2n) { float: left; }
6.6.5.5. :nth-last-of-type() 伪类

:nth-last-of-type(an+b) 伪类表示在文档树中,其后(之后)有 an+b-1 个拥有相同展开元素名的兄弟,n 为任意零或正整数。该元素不必有父元素。其参数语法同 :nth-child(),并接受 ‘even’ 与 ‘odd’。

示例

若要表示 XHTML body 中除首个与末尾外的所有 h2 子元素,可使用如下选择器:

body > h2:nth-of-type(n+2):nth-last-of-type(n+2)

在这种情况下,也可以使用 :not(),虽然选择器的长度仍然相同。

body > h2:not(:first-of-type):not(:last-of-type)
6.6.5.6. :first-child 伪类

等同于 :nth-child(1):first-child 伪类表示在兄弟列表中首位的元素。

示例

下面的选择器表示 div 元素的第一个子元素 p

div > p:first-child

该选择器可以匹配以下片段中 div 内的 p

<p> The last P before the note.</p>
<div class="note">
   <p> The first P inside the note.</p>
</div>
但不能匹配以下片段中的第二个 p
<p> The last P before the note.</p>
<div class="note">
   <h2> Note </h2>
   <p> The first P inside the note.</p>
</div>

下面的两个选择器通常是等价的。

* > a:first-child /* a is first child of any element */
a:first-child /* Same (assuming a is not the root element) */
6.6.5.7. :last-child 伪类

等同于 :nth-last-child(1):last-child 伪类表示在兄弟列表中最后的元素。

示例

下面的选择器表示有序列表 ol 中的最后一个子项 li

ol > li:last-child
6.6.5.8. :first-of-type 伪类

等同于 :nth-of-type(1):first-of-type 伪类表示同类型兄弟中的首位元素。

示例

下面的选择器表示定义列表 dl 中的定义标题 dt,即该父元素子元素列表中首个 dt

dl dt:first-of-type

它对以下示例中前两个 dt 元素有效,但对第三个不适用。

<dl>
 <dt>gigogne</dt>
 <dd>
  <dl>
   <dt>fusée</dt>
   <dd>multistage rocket</dd>
   <dt>table</dt>
   <dd>nest of tables</dd>
  </dl>
 </dd>
</dl>
6.6.5.9. :last-of-type 伪类

等同于 :nth-last-of-type(1):last-of-type 伪类表示同类型兄弟中的最后一个元素。

示例

下面的选择器表示表格行 tr 中的最后一个数据单元格 td

tr > td:last-of-type
6.6.5.10. :only-child 伪类

:only-child 伪类表示没有任何兄弟的元素。等价于 :first-child:last-child:nth-child(1):nth-last-child(1),但 specificity 更低。

6.6.5.11. :only-of-type 伪类

:only-of-type 伪类表示没有同类型兄弟的元素。等价于 :first-of-type:last-of-type:nth-of-type(1):nth-last-of-type(1),但 specificity 更低。

6.6.5.12. :empty 伪类

:empty 伪类表示没有任何子节点的元素。就文档树而言,只有元素节点和内容节点(如 DOM [DOM-LEVEL-3-CORE] 的文本节点、CDATA 节点和实体引用节点)且其数据长度非零时才会影响“空”属性;注释、处理指令以及其他节点不应影响元素是否被视为为空。

示例

p:empty 是对以下片段的有效表示。

<p></p>

foo:empty 不是对以下片段的有效表示。

<foo>bar</foo>
<foo><bar>bla</bar></foo>
<foo>this is not <bar>:empty</bar></foo>

6.6.6. 空白

本节特意留空。(本节之前曾定义过 :contains() 伪类。)

6.6.7. 否定伪类

否定伪类 :not(X) 是一种函数式记法,接受一个 简单选择器(不能是否定伪类本身)作为参数。它表示不匹配该参数所表示的元素。

否定不能嵌套;:not(:not(...)) 是无效的。还需注意,伪元素不是简单选择器,因而不能作为 :not() 的参数。

示例

下面的选择器匹配 HTML 文档中所有未被禁用的 button 元素。

button:not([DISABLED])

下面的选择器表示除 FOO 元素之外的所有元素。

*:not(FOO)

下面的一组选择器表示除链接之外的所有 HTML 元素。

html|*:not(:link):not(:visited)

默认命名空间声明不会影响否定伪类的参数,除非参数是通用选择器或类型选择器。

示例

假设默认命名空间绑定到 “http://example.com/”,下面的选择器表示所有不在该命名空间中的元素。

*|*:not(*)

下面的选择器匹配任何未被悬停的元素,无论其所属命名空间如何。具体而言,它并不局限于只匹配默认命名空间中未被悬停的元素,而当元素 **已** 被悬停且不在默认命名空间时,则不匹配该规则。

*|*:not(:hover)

注意: :not() 伪类允许编写无意义的选择器。例如 :not(*|*) 表示根本没有任何元素,或者 foo:not(bar)foo 等价但 specificity 更高。

7. 伪元素

伪元素在文档树之上创建抽象,以实现文档语言未提供的功能。例如,文档语言并未提供访问元素内容的首字母或首行的机制。伪元素允许作者引用这些本来不可访问的信息。伪元素还可以让作者引用源文档中不存在的内容(例如 ::before::after 伪元素提供了对生成内容的访问)。

伪元素由两个冒号 (::) 加上伪元素名称构成。

当前文档引入了此 :: 记法,以在伪类与伪元素之间建立区分。为兼容现有样式表,用户代理仍须接受 CSS 1 与 CSS 2 中引入的单冒号记法的伪元素(即 :first-line:first-letter:before:after)。对本规范中新引入的伪元素则不允许使用单冒号记法。

每个选择器最多只能出现一个伪元素,且若出现必须位于表示 主题 的简单选择器序列之后。注意: 本规范的未来版本可能允许在同一选择器中出现多个伪元素。

7.1. ::first-line 伪元素

::first-line 伪元素描述元素第一行已经排版好的内容。

CSS 示例

p::first-line { text-transform: uppercase }

上述规则表示 “将每个 p 元素第一行的字母转换为大写”。

选择器 p::first-line 并不匹配实际的文档元素。它匹配一个符合规范的用户代理将在每个 p 元素的起始位置插入的伪元素。

请注意,第一行的长度取决于多种因素,包括页面宽度、字号等。因此,一个普通的 HTML 段落如

<P>This is a somewhat long HTML
paragraph that will be broken into several
lines. The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

其行可能会被分割如下

THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT
will be broken into several lines. The first
line will be identified by a fictional tag
sequence. The other lines will be treated as
ordinary lines in the paragraph.

此段落可能会被用户代理“改写”,以包含 ::first-line虚构标记序列。该虚构序列有助于展示属性的继承方式。

<P><P::first-line> This is a somewhat long HTML
paragraph that </P::first-line> will be broken into several
lines. The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

如果伪元素将真实元素拆分,期望的效果通常可以通过一个先关闭再重新打开该元素的虚构标记序列来描述。因此,我们可以在前面的段落中使用 span 元素进行标记:

<P><SPAN class="test"> This is a somewhat long HTML
paragraph that will be broken into several
lines.</SPAN> The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

用户代理在为 ::first-line 插入虚构标记序列时,可模拟 span 的开始与结束标签。

<P><P::first-line><SPAN class="test"> This is a
somewhat long HTML
paragraph that will </SPAN></P::first-line><SPAN class="test"> be
broken into several
lines.</SPAN> The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

7.1.1. CSS 中的首行定义

在 CSS 中,::first-line 伪元素仅在附着于块级容器(如块盒、inline‑block、table‑caption 或 table‑cell)时才会产生效果。在这种情况下,它指向该容器的 首个已排版的行

元素的首个已排版行可能出现在同一流中的块级后代内部(即未因浮动或定位而脱离流的块级后代)。例如,<DIV><P>This line...</P></DIV> 中的 DIV 的首行即为 P 的首行(前提是 PDIV 均为块级元素)。

表格单元格或 inline‑block 的首行不能成为祖先元素的首个已排版行。因此,在 <DIV><P STYLE="display: inline-block">Hello<BR>Goodbye</P> etcetera</DIV> 中,DIV 的首个已排版行并不是 “Hello”。

注意:请注意在以下片段中 p 的首行:<p><br>First... 并不包含任何字母(假设 br 在 HTML 4 中的默认样式)。单词 “First” 并不在首个已排版行上。

用户代理应当表现得好像 ::first-line 伪元素的虚构开始标签仅嵌套在最内层的块级元素内部。(由于 CSS1 与 CSS2 对此情况未作说明,作者不应依赖该行为。)例如,下面的虚构标记序列:

<DIV>
  <P>First paragraph</P>
  <P>Second paragraph</P>
</DIV>

<DIV>
  <P><DIV::first-line><P::first-line>First paragraph</P::first-line></DIV::first-line></P>
  <P><P::first-line>Second paragraph</P::first-line></P>
</DIV>

::first-line 伪元素类似于行内元素,但有若干限制。以下 CSS 属性适用于 ::first-line 伪元素:字体属性、颜色属性、背景属性、word-spacingletter-spacingtext-decorationtext-transformline-height。用户代理还可能应用其他属性。

在 CSS 继承期间,仅位于首行的子元素部分会从 ::first-line 伪元素继承适用于该伪元素的属性。对于所有其他属性,则从首行伪元素的非伪元素父节点继承。(不在首行的子元素部分始终从其父元素继承。)

7.2. ::first-letter 伪元素

::first-letter 伪元素表示元素的第一个字母,前提是其所在行没有其他内容(如图片或行内表格)在其之前。::first-letter 常用于实现 “首字母大写” 与 “首字下沉”,这两种效果在排版中很常见。

先行或后随第一个字母的标点(即 Unicode 中的 “开”(Ps)、“闭”(Pe)、“首”(Pi)、“末”(Pf) 与 “其他”(Po) 标点类)应被计入。[UNICODE]

Quotes that precede the first letter should be included.

::first-letter 也适用于首字母实际上是数字的情况,例如 “67 million dollars is a lot of money” 中的 “6”。

注意:在某些情况下,::first-letter 应当包括行首的多个字符,而不仅仅是第一个非标点字符。例如,组合字符必须与其基础字符一起保留。此外,某些语言对特定字母组合有特殊规则。UA 对 ::first-letter 的定义应至少包含 UAX29 所定义的默认字形集(grapheme cluster),并可根据需要包含更多内容。例如,在荷兰语中,若元素开头出现字母组合 “ij”,则该组合的两个字母都应视为 ::first-letter 的一部分。[UAX29]

如果构成 ::first-letter 的字母不在同一元素中,例如在 <p>‘<em>T... 中的 “‘T”,则 UA 可以从单个元素、两个元素,或根本不创建伪元素。

同理,如果块级元素的首字母(或首字母组合)并未位于行首(例如因双向文本重排),则 UA 可以不创建相应的伪元素。

示例

以下 CSS 与 HTML 示例 展示了重叠伪元素可能的交互方式。每个 P 元素的首字母将显示为绿色,字号为 ‘24pt’。首行其余部分为 ‘blue’;段落其余部分为 ‘red’。

p { color: red; font-size: 12pt }
p::first-letter { color: green; font-size: 200% }
p::first-line { color: blue }

<P>Some text that ends up on two lines</P>

假设在单词 “ends” 前会换行,则该片段的 虚构标记序列 可能为:

<P>
<P::first-line>
<P::first-letter>
S
</P::first-letter>ome text that
</P::first-line>
ends up on two lines
</P>

请注意,::first-letter 元素位于 ::first-line 元素内部。在 ::first-line 上设置的属性会被 ::first-letter 继承,但如果相同属性在 ::first-letter 上也被设置,则会覆盖前者。

首字母必须出现在第一行已格式化的行上。例如,在此 HTML 片段中:<p><br>First... 第一行不包含任何字母,且 ::first-letter 并未匹配到任何内容(假设 HTML 4 中 br 的默认样式)。尤其是,它不会匹配 “First” 中的 “F”。

7.2.1. 在 CSS 中的应用

在 CSS 中,::first-letter 伪元素适用于块级容器,例如 block、list-item、table-cell、table-caption 以及 inline‑block 元素。注: 本规范的未来版本可能允许此伪元素适用于更多的 display 类型。

::first-letter 伪元素可用于所有包含文本的此类元素,或其同一流中的后代包含文本的情况。用户代理应当把 ::first-letter 伪元素的虚构起始标签视为位于元素的第一段文本之前,即使该第一段文本位于后代中。

示例

此 HTML 片段的虚构标签序列

<div>
<p>The first text.

<div>
<p><div::first-letter><p::first-letter>T</...></...>he first text.

在 CSS 中,table‑cell 或 inline‑block 的首字母不能成为其祖先元素的首字母。因此,在 <DIV><P STYLE="display: inline-block">Hello<BR>Goodbye</P> etcetera</DIV> 中,DIV 的首字母不是 “H”。事实上,DIV 并没有首字母。

如果元素是列表项(display: list-item),::first-letter 作用于标记之后的主体框中的第一个字母。对于 list-style-position: inside 的列表项,用户代理可能会忽略 ::first-letter。若元素拥有 ::before::after 内容,::first-letter 将作用于包括该内容在内的元素的第一个字母。

示例

在规则 p::before {content: "Note: "} 之后,选择器 p::first-letter 匹配 “Note” 中的 “N”。

在 CSS 中,若 float 属性为 none,则 ::first-line 伪元素类似于内联元素;否则,它类似于浮动元素。以下属性适用于 ::first-letter 伪元素:字体属性、text-decorationtext-transformletter-spacingword-spacing(视情况而定)、line-heightfloatvertical-align(仅当 floatnone 时)、外边距属性、内边距属性、边框属性、颜色属性、背景属性。用户代理也可能应用其他属性。为了让用户代理能够渲染排版上正确的首字母或首行字母,用户代理可以根据字母形状选择行高、宽度和高度,这一点与普通元素不同。

示例

以下 CSS 与 HTML 示例展示了一种可能的首字母渲染方式。注意,::first-letter 伪元素继承的 line-height 为 1.1,但本例中的 UA 对首字母的高度计算方式不同,因而不会在前两行之间产生不必要的空隙。同时请注意,首字母的虚构起始标签位于 span 内部,因此首字母的字体粗细为普通(normal),而不是 span 那样的粗体。

p { line-height: 1.1 }
p::first-letter { font-size: 3em; font-weight: normal }
span { font-weight: bold }
...
<p><span>Het hemelsche</span> gerecht heeft zich ten lange lesten<br>
Erbarremt over my en mijn benaeuwde vesten<br>
En arme burgery, en op mijn volcx gebed<br>
En dagelix geschrey de bange stad ontzet.

Image illustrating the ::first-letter pseudo-element

以下 CSS 将使首字母下沉并跨越约两行

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
 <HEAD>
  <TITLE>Drop cap initial letter</TITLE>
  <STYLE type="text/css">
   P               { font-size: 12pt; line-height: 1.2 }
   P::first-letter { font-size: 200%; font-weight: bold; float: left }
   SPAN            { text-transform: uppercase }
  </STYLE>
 </HEAD>
 <BODY>
  <P><SPAN>The first</SPAN> few words of an article
    in The Economist.</P>
 </BODY>
</HTML>

此示例可能的排版如下:

Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements

虚构标签序列是

<P>
<SPAN>
<P::first-letter>
T
</P::first-letter>he first
</SPAN>
few words of an article in the Economist.
</P>

请注意,::first-letter 伪元素标签紧贴内容(即初始字符),而 ::first-line 伪元素的起始标签则插入在块级元素的起始标签之后。

为了实现传统的首字母放大排版,用户代理可以对字体大小进行近似计算,例如对齐基线。同时,字形轮廓在排版时也可以被考虑进来。

7.3. 空白

本节特意留空。(本节以前定义了 ::selection 伪元素。)

7.4. ::before 与 ::after 伪元素

::before::after 伪元素可用于描述元素内容之前或之后产生的内容。它们在 CSS 2.1 [CSS21] 中有解释。

::first-letter::first-line 伪元素应用于使用 ::before::after 生成内容的元素时,它们同样作用于包括生成内容在内的元素的首字母或首行。

8. 组合符

8.1. 后代组合符

有时,作者希望选择器描述文档树中另一个元素的后代(例如 “一个位于 H1 元素内部的 EM 元素”)。后代组合符用于表达这种关系。后代组合符是将两组简单选择器分开的空白字符。形如 “A B” 的选择器表示元素 B 是元素 A 任意后代。

示例

例如,考虑下面的选择器

h1 em

它表示一个 em 元素是 h1 元素的后代。这是对下面片段的正确且有效(但不完整)的描述

<h1>This <span class="myclass">headline
is <em>very</em> important</span></h1>

以下选择器

div * p

它表示一个 p 元素是 div 元素的孙子或更深层的后代。请注意,星号两侧的空白并不是通用选择器的一部分;这些空白是组合符,表示 div 必须是某元素的祖先,而该元素又必须是 p 的祖先。

下面的选择器结合了后代组合符和属性选择器,表示一个(1)拥有 href 属性且(2)位于 p 元素内部,而该 p 本身又位于 div 内的元素。

div p *[href]

8.2. 子代组合符

一个子组合符描述两个元素之间的子层关系。子组合符由“大于号”(U+003E,>)组成,用来分隔两组简单选择器。

示例

下面的选择器表示一个 p 元素是 body 的子元素。

body > p

以下示例将后代组合符与子组合符结合使用。

div ol>li p

它表示一个 p 元素是 li 元素的后代;该 li 必须是 ol 的子元素;ol 必须是 div 的后代。请注意,围绕 “>” 组合符的可选空白已被省略。

有关选取元素第一个子元素的信息,请参见上文关于 :first-child 伪类的章节。

8.3. 同级组合符

兄弟组合符有两种:后继兄弟组合符(next‑sibling)和随后的兄弟组合符(subsequent‑sibling)。在两种情况下,非元素节点(例如元素之间的文本)在判断元素相邻性时都会被忽略。

8.3.1. 相邻同级组合符

后继兄弟组合符由“加号”(U+002B,+)字符组成,用来分隔两组简单选择器。两组选择器对应的元素共享同一文档树父节点,且第一组对应的元素紧接在第二组对应的元素之前。

示例

下面的选择器表示一个 p 元素紧随在一个 math 元素之后。

math + p

下面的选择器在概念上类似于前例,只是它额外加入了属性选择器——对 h1 元素加了约束,要求其必须具有 class="opener"

h1.opener + h2

8.3.2. 后续同级组合符

随后的兄弟组合符由“波浪号”(U+007E,~)字符组成,用来分隔两组简单选择器。两组选择器对应的元素共享同一文档树父节点,且第一组对应的元素在第二组对应的元素之前(但不一定紧邻)。

示例

h1 ~ pre

它表示一个 pre 元素位于 h1 之后。这是对以下内容的正确且有效(但不完整)的描述

<h1>Definition of the function a</h1>
<p>Function a(x) has to be applied to all figures in the table.</p>
<pre>function a(x) = 12x/13.5</pre>

9. 计算选择器的特异性

选择器的特异性计算如下

位于否定伪类内部的选择器也按通常方式计数,但否定本身不计为伪类。

将三个数字 a‑b‑c(在一个大基数的数制中)串联得到特异性。

示例

*               /* a=0 b=0 c=0 -> specificity =   0 */
LI              /* a=0 b=0 c=1 -> specificity =   1 */
UL LI           /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI        /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red    /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level    /* a=0 b=2 c=1 -> specificity =  21 */
#x34y           /* a=1 b=0 c=0 -> specificity = 100 */
#s12:not(FOO)   /* a=1 b=0 c=1 -> specificity = 101 */

注: 同一简单选择器的重复出现是允许的,并且会增加特异性。

注: 在 HTML style 属性中指定的样式的特异性在 CSS 2.1 中已有说明。[CSS21]

10. 选择器的语法

10.1. 语法

下面的文法定义了 Selectors 的语法。它整体是 LL(1) 的,在局部可视为 LL(2)(但请注意,大多数用户代理不应直接使用它,因为它并未表达解析约定)。产生式的格式针对人类阅读进行了优化,并使用了超出 Yacc 的一些简写记法(见 [YACC])。

产生式为

selectors_group
  : selector [ COMMA S* selector ]*
  ;

selector
  : simple_selector_sequence [ combinator simple_selector_sequence ]*
  ;

combinator
  /* combinators can be surrounded by whitespace */
  : PLUS S* | GREATER S* | TILDE S* | S+
  ;

simple_selector_sequence
  : [ type_selector | universal ]
    [ HASH | class | attrib | pseudo | negation ]*
  | [ HASH | class | attrib | pseudo | negation ]+
  ;

type_selector
  : [ namespace_prefix ]? element_name
  ;

namespace_prefix
  : [ IDENT | '*' ]? '|'
  ;

element_name
  : IDENT
  ;

universal
  : [ namespace_prefix ]? '*'
  ;

class
  : '.' IDENT
  ;

attrib
  : '[' S* [ namespace_prefix ]? IDENT S*
        [ [ PREFIXMATCH |
            SUFFIXMATCH |
            SUBSTRINGMATCH |
            '=' |
            INCLUDES |
            DASHMATCH ] S* [ IDENT | STRING ] S*
        ]? ']'
  ;

pseudo
  /* '::' starts a pseudo-element, ':' a pseudo-class */
  /* Exceptions: :first-line, :first-letter, :before and :after. */
  /* Note that pseudo-elements are restricted to one per selector and */
  /* occur only in the last simple_selector_sequence. */
  : ':' ':'? [ IDENT | functional_pseudo ]
  ;

functional_pseudo
  : FUNCTION S* expression ')'
  ;

expression
  /* In CSS3, the expressions are identifiers, strings, */
  /* or of the form "an+b" */
  : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+
  ;

negation
  : NOT S* negation_arg S* ')'
  ;

negation_arg
  : type_selector | universal | HASH | class | attrib | pseudo
  ;

10.2. 词法扫描器

以下是 分词器,使用 Flex(见 [FLEX])记法编写。分词器对大小写不敏感。

两次出现的 “\377” 代表当前版本的 Flex 能处理的最高字符编号(十进制 255)。它们应当被读取为 “\4177777”(十进制 1114111),即 Unicode/ISO‑10646 中可能的最高码位。[UNICODE]

%option case-insensitive

ident     [-]?{nmstart}{nmchar}*
name      {nmchar}+
nmstart   [_a-z]|{nonascii}|{escape}
nonascii  [^\0-\177]
unicode   \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
escape    {unicode}|\\[^\n\r\f0-9a-f]
nmchar    [_a-z0-9-]|{nonascii}|{escape}
num       [0-9]+|[0-9]*\.[0-9]+
string    {string1}|{string2}
string1   \"([^\n\r\f\\"]|\\{nl}|{nonascii}|{escape})*\"
string2   \'([^\n\r\f\\']|\\{nl}|{nonascii}|{escape})*\'
invalid   {invalid1}|{invalid2}
invalid1  \"([^\n\r\f\\"]|\\{nl}|{nonascii}|{escape})*
invalid2  \'([^\n\r\f\\']|\\{nl}|{nonascii}|{escape})*
nl        \n|\r\n|\r|\f
w         [ \t\r\n\f]*

D         d|\\0{0,4}(44|64)(\r\n|[ \t\r\n\f])?
E         e|\\0{0,4}(45|65)(\r\n|[ \t\r\n\f])?
N         n|\\0{0,4}(4e|6e)(\r\n|[ \t\r\n\f])?|\\n
O         o|\\0{0,4}(4f|6f)(\r\n|[ \t\r\n\f])?|\\o
T         t|\\0{0,4}(54|74)(\r\n|[ \t\r\n\f])?|\\t
V         v|\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\v

%%

[ \t\r\n\f]+     return S;

"~="             return INCLUDES;
"|="             return DASHMATCH;
"^="             return PREFIXMATCH;
"$="             return SUFFIXMATCH;
"*="             return SUBSTRINGMATCH;
{ident}          return IDENT;
{string}         return STRING;
{ident}"("       return FUNCTION;
{num}            return NUMBER;
"#"{name}        return HASH;
{w}"+"           return PLUS;
{w}">"           return GREATER;
{w}","           return COMMA;
{w}"~"           return TILDE;
":"{N}{O}{T}"("  return NOT;
@{ident}         return ATKEYWORD;
{invalid}        return INVALID;
{num}%           return PERCENTAGE;
{num}{ident}     return DIMENSION;
"<!--"           return CDO;
"-->"            return CDC;

\/\*[^*]*\*+([^/*][^*]*\*+)*\/                    /* ignore comments */

.                return *yytext;

11. 配置文件

每个使用 Selectors 的规范必须定义其允许和排除的 Selectors 子集,并描述该子集所有组成部分的局部含义。

非规范性示例

Selectors 配置文件
规范CSS 第 1 级
接受类型选择器
类选择器
ID 选择器
:link、:visited 与 :active 伪类
后代组合器
::first-line 与 ::first-letter 伪元素
排除项

通用选择器
属性选择器
:hover 与 :focus 伪类
:target 伪类
:lang() 伪类
所有 UI 元素状态伪类
所有结构性伪类
否定伪类
::before 与 ::after 伪元素
子组合符
兄弟组合符

namespaces

额外约束每个简单选择器序列只能包含一个类选择器


Selectors 配置文件
规范CSS 第 2 级
接受类型选择器
通用选择器
属性存在性与取值选择器
类选择器
ID 选择器
:link、:visited、:active、:hover、:focus、:lang() 与 :first-child 伪类
后代组合器
子组合符
紧邻兄弟组合器
::first-line 与 ::first-letter 伪元素
::before 与 ::after 伪元素
排除项

子字符串匹配属性选择器
:target 伪类
所有 UI 元素状态伪类
除 :first-child 外的所有结构性伪类
否定伪类
随后的兄弟组合符

namespaces

额外约束允许在一个简单选择器序列中出现多个类选择器(CSS1 约束)

在 CSS 中,选择器表达模式匹配规则,以决定文档树中哪些元素会受到特定样式规则的影响。

下面的选择器(CSS 2 级)将 匹配所有位于 h1 标题内部、且拥有 name 属性的锚点 a

h1 a[name]

所有附属于该选择器的 CSS 声明都会应用到匹配的元素上。

Selectors 配置文件
规范STTS 3
接受

类型选择器
通用选择器
属性选择器
类选择器
ID 选择器
所有结构性伪类
所有组合符

namespaces

排除项不接受的伪类
pseudo-elements
额外约束在 STTS 声明右侧的片段描述中,某些选择器和组合符是不被允许的。

在 STTS 3 中,选择器可用于两种不同的方式

  1. 一种等同于 CSS 选择机制的选择机制:附加到给定选择器的声明会应用到匹配该选择器的元素上,
  2. 另一种是出现在声明右侧的片段描述。

12. 符合性与要求

本节仅定义与当前规范的符合性。

由于特定设备的限制(例如,非交互式用户代理可能不会实现动态伪类,因为在没有交互性时它们毫无意义),用户代理无法实现本规范的某些部分并不构成不符合性。

所有复用 Selectors 的规范必须包含一个配置文件,列出其接受或排除的 Selectors 子集,并描述其对当前规范所添加的约束。

无效性由解析错误引起,例如未识别的 token 或在当前解析点不允许的 token。

用户代理必须遵守处理解析错误的规则。

复用 Selectors 的规范必须定义如何处理解析错误。(在 CSS 中,使用该选择器的整条规则会被丢弃。)

13. 测试

本规范拥有测试套件,帮助用户代理验证其对规范的基本符合性。该套件并不声称覆盖所有情况,也未涵盖所有可能的组合案例。

14. 致谢

CSS 工作组感谢多年来向本规范提供意见的所有人士。

特别感谢 Donna McManus、Justin Baker、Joel Sklar 与 Molly Ives Brower 对最后一次草案的终稿编辑审查,以及 Adam Kuehn、Boris Zbarsky、David Perrell、Elliotte Harold、Matthew Raymond、Ruud Steltenpool、Patrick Garies、Anton Prowse 与 W3C 国际化工作组在最后一次征求意见期间的评论与鼓励。

15. 参考文献

15.1. 规范性参考文献

[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011 年 6 月 7 日. W3C Recommendation. URL: https://w3org.cn/TR/2011/REC-CSS2-20110607
[CSS3NAMESPACE]
Elika J. Etemad. CSS Namespaces Module Level 3. 2011 年 9 月 29 日. W3C Recommendation. URL: https://w3org.cn/TR/2014/REC-css-namespaces-3-20140320/
[FLEX]
Flex: The Lexical Scanner Generator. 版本 2.3.7, ISBN 1882114213
[UNICODE]
The Unicode Consortium. The Unicode Standard. 2012. 定义于:Unicode Standard, Version 6.2.0 (Mountain View, CA: The Unicode Consortium, 2012. ISBN 978-1-936213-07-8),并随新版本的发布不时更新。URL: http://www.unicode.org/standard/versions/enumeratedversions.html
[YACC]
S. C. Johnson. YACC - Yet another compiler compiler. Murray Hill. 1975. Technical Report.

15.2. 参考性文献

[BCP47]
A. Phillips; M. Davis. Tags for Identifying Languages. 2009 年 9 月. BCP 47. 当前以 RFC 5646 形式呈现。URL: ftp://ftp.rfc-editor.org/in-notes/bcp/bcp47.txt
[CSS1]
Håkon Wium Lie; Bert Bos. Cascading Style Sheets (CSS1) Level 1 Specification. 2008 年 4 月 11 日. W3C Recommendation. URL: https://w3org.cn/TR/2008/REC-CSS1-20080411
[DOM-LEVEL-3-CORE]
Gavin Nicol; et al. Document Object Model (DOM) Level 3 Core Specification. 2004 年 4 月 7 日. W3C Recommendation. URL: https://w3org.cn/TR/2004/REC-DOM-Level-3-Core-20040407
[HTML401]
Dave Raggett; Arnaud Le Hors; Ian Jacobs. HTML 4.01 Specification. 24 December 1999. W3C Recommendation. URL: https://w3org.cn/TR/1999/REC-html401-19991224
[HTML5]
Ian Hickson; et al. HTML5. 2014 年 10 月 28 日. W3C Recommendation. URL: https://w3org.cn/TR/2014/REC-html5-20141028/
[MATHML3]
David Carlisle; Patrick Ion; Robert Miner. Mathematical Markup Language (MathML) Version 3.0 2nd Edition. 2014 年 4 月 10 日. W3C Recommendation. URL: https://w3org.cn/TR/2014/REC-MathML3-20140410/
[STTS3]
Daniel Glazman. Simple Tree Transformation Sheets 3. 法国电力公司(Electricité de France). 1998 年 11 月 11 日. 向 W3C 提交。URL: https://w3org.cn/TR/NOTE-STTS3
[SVG11]
Erik Dahlström; et al. Scalable Vector Graphics (SVG) 1.1 (Second Edition). 16 August 2011. W3C Recommendation. URL: https://w3org.cn/TR/2011/REC-SVG11-20110816/
[UAX29]
Mark Davis. Unicode Text Segmentation. 2012 年 9 月 12 日. Unicode Standard Annex #29. URL: http://www.unicode.org/reports/tr29/
[XML-NAMES]
Tim Bray; et al. Namespaces in XML 1.0 (Third Edition). 2009 年 12 月 8 日. W3C Recommendation. URL: https://w3org.cn/TR/2009/REC-xml-names-20091208/
[XML10]
C. M. Sperberg‑McQueen; et al. Extensible Markup Language (XML) 1.0 (Fifth Edition). 2008 年 11 月 26 日. W3C Recommendation. URL: https://w3org.cn/TR/2008/REC-xml-20081126/

15.3. 更改

自上一次 Recommendation 起的实质性变更包括