1. 简介
本节不具规范性。
选择器是一个布尔谓词, 用于接收树结构中的元素, 并测试该元素是否匹配此选择器。
这些表达式可用于多种场景:
- 直接作用于某个元素以测试其是否符合某些条件,
例如在[DOM]中定义的
element.matches()
函数 - 应用于整个元素树,
以筛选出符合条件的一组元素,
例如在[DOM]中定义的
document.querySelectorAll()
函数或CSS样式规则中的选择器。 - “反向”使用以生成能够匹配指定选择器的标记, 例如在HAML或Emmet中。
选择器等级1、2和3分别在CSS1、CSS2.1和选择器等级3规范中定义。本模块定义了选择器等级4。
1.1. 模块交互
本模块替换并扩展了[SELECT]和[CSS21]中为CSS定义的选择器集合及相关定义。
伪元素选择器, 用于定义渲染树中的抽象元素, 不属于本规范范畴: 本规范仅描述其通用语法, 由于伪元素选择器与渲染模型紧密集成,且对DOM查询等其他用途无关, 它们将在其他模块中定义。
2. 选择器概述
本节不具规范性,仅对后续章节进行总结。
选择器表示一种结构。该结构可以作为条件(如在CSS规则中)用于确定选择器在文档树中匹配哪些元素,也可以作为对应结构的HTML或XML片段的扁平描述。
选择器可以从简单的元素名称到丰富的上下文表达。
下表总结了选择器语法:
模式 | 表示 | 章节 | 等级 |
---|---|---|---|
*
| 任意元素 | § 5.2 通用选择器 | 2 |
E
| 类型为E的元素 | § 5.1 类型(标签名)选择器 | 1 |
E:not(s1, s2, …)
| 不匹配复合选择器s1或复合选择器s2的E元素 | § 4.3 否定(不匹配)伪类::not() | 3/4 |
E:is(s1, s2, …)
| 匹配复合选择器s1和/或复合选择器s2的E元素 | § 4.2 任意匹配伪类::is() | 4 |
E:where(s1, s2, …)
| 匹配复合选择器s1和/或复合选择器s2但不贡献特异性的E元素 | § 4.4 特异性调整伪类::where() | 4 |
E:has(rs1, rs2, …)
| 如果存在与相对选择器rs1或rs2匹配的元素,以E作为锚点元素评估时,则E元素 | § 4.5 关系伪类::has() | 4 |
E.warning
| 属于类warning 的E元素(文档语言规定类的确定方式)
| § 6.6 类选择器 | 1 |
E#myid
| ID等于myid 的E元素
| § 6.7 ID选择器 | 1 |
E[foo]
| 具有foo 属性的E元素
| § 6.1 属性存在与值选择器 | 2 |
E[foo="bar"]
| foo 属性值正好为bar 的E元素
| § 6.1 属性存在与值选择器 | 2 |
E[foo="bar" i]
| foo 属性值为任意(ASCII范围)大小写组合的bar 的E元素
| § 6.3 大小写敏感性 | 4 |
E[foo="bar" s]
| foo 属性值与bar 完全相同的E元素
| § 6.3 大小写敏感性 | 4 |
E[foo~="bar"]
| foo 属性值为由空格分隔的值列表,其中之一正好为bar 的E元素
| § 6.1 属性存在与值选择器 | 2 |
E[foo^="bar"]
| foo 属性值正好以字符串bar 开头的E元素
| § 6.2 子串匹配属性选择器 | 3 |
E[foo$="bar"]
| foo 属性值正好以字符串bar 结尾的E元素
| § 6.2 子串匹配属性选择器 | 3 |
E[foo*="bar"]
| foo 属性值包含子串bar 的E元素
| § 6.2 子串匹配属性选择器 | 3 |
E[foo|="en"]
| foo 属性值为以en 开头的连字符分隔值列表的E元素
| § 6.1 属性存在与值选择器 | 2 |
E:dir(ltr)
| 类型为E且方向性为从左到右的元素(文档语言规定方向性确定方式) | § 7.1 方向性伪类::dir() | 4 |
E:lang(zh, "*-hant")
| 类型为E且标记为中文(任意方言或书写系统)或以繁体中文字符书写的元素 | § 7.2 语言伪类::lang() | 2/4 |
E:any-link
| 作为超链接源锚点的E元素 | § 8.1 超链接伪类::any-link | 4 |
E:link
| 作为超链接源锚点且目标尚未访问的E元素 | § 8.2 链接历史伪类::link和:visited | 1 |
E:visited
| 作为超链接源锚点且目标已访问的E元素 | § 8.2 链接历史伪类::link和:visited | 1 |
E:local-link
| 作为超链接源锚点且目标为当前URL的E元素 | § 8.3 本地链接伪类::local-link | 4 |
E:target
| 作为当前URL目标的E元素 | § 8.4 目标伪类::target | 3 |
E:target-within
| 作为当前URL目标或包含目标元素的E元素 | § 8.5 目标容器伪类::target-within | 4 |
E:scope
| 作为作用域根的E元素 | § 8.6 参考元素伪类::scope | 4 |
E:current
| 当前在时间维度画布中呈现的E元素 | § 10.1 当前元素伪类::current | 4 |
E:current(s)
| 匹配选择器s的最深:current元素的E元素 | § 10.1 当前元素伪类::current | 4 |
E:past
| 在时间维度画布中属于过去的E元素 | § 10.2 过去元素伪类::past | 4 |
E:future
| 在时间维度画布中属于未来的E元素 | § 10.3 未来元素伪类::future | 4 |
E:active
| 处于激活状态的E元素 | § 9.2 激活伪类::active | 1 |
E:hover
| 在光标下或其后代在光标下的E元素 | § 9.1 指针悬停伪类::hover | 2 |
E:focus
| 获得用户输入焦点的E元素 | § 9.3 输入焦点伪类::focus | 2 |
E:focus-within
| 获得用户输入焦点或包含获得输入焦点元素的E元素 | § 9.5 焦点容器伪类::focus-within | 4 |
E:focus-visible
| 获得用户输入焦点,且UA确定应为该元素绘制焦点环或其它指示器的E元素 | § 9.4 焦点可视伪类::focus-visible | 4 |
E:enabled
| 启用或禁用的用户界面元素E | § 13.1.1 :enabled和:disabled伪类 | 3 |
E:read-write E:read-only
| 可由用户更改或不可更改的用户界面元素E | § 13.1.2 可变性伪类::read-only和:read-write | 3-UI/4 |
E:placeholder-shown
| 当前显示占位符文本的输入控件 | § 13.1.3 占位符显示伪类::placeholder-shown | 3-UI/4 |
E:default
| 在一组相关选项中为默认项的用户界面元素E | § 13.1.5 默认选项伪类::default | 3-UI/4 |
E:checked
| 被选中/勾选的用户界面元素E(如单选按钮或复选框) | § 13.2.1 选中选项伪类::checked | 3 |
E:indeterminate
| 处于不确定状态(既非选中也非未选中)的用户界面元素E | § 13.2.2 不确定值伪类::indeterminate | 4 |
E:valid E:invalid
| 满足或不满足数据有效性语义的用户输入元素E | § 13.3.2 有效性伪类::valid和:invalid | 3-UI/4 |
E:in-range E:out-of-range
| 值在范围内/超出范围的用户输入元素E | § 13.3.3 范围伪类::in-range和:out-of-range | 3-UI/4 |
E:required E:optional
| 需要输入/不需要输入的用户输入元素E | § 13.3.4 可选性伪类::required和:optional | 3-UI/4 |
E:blank
| 值为空(空或缺失)的用户输入元素E | § 13.3.1 空值伪类::blank | 4 |
E:user-invalid
| 由用户更改且输入不正确(无效、超出范围、遗漏但必填)的用户输入元素E | § 13.3.5 用户交互伪类::user-valid和:user-invalid | 4 |
E:root
| 作为文档根的E元素 | § 14.1 :root伪类 | 3 |
E:empty
| 没有任何子元素(既无元素也无文本,仅可能有空白)的E元素 | § 14.2 :empty伪类 | 3 |
E:nth-child(n [of S]?)
| 作为其父元素第n个且匹配S的E元素 | § 14.3.1 :nth-child()伪类 | 3/4 |
E:nth-last-child(n [of S]?)
| 作为其父元素倒数第n个且匹配S的E元素 | § 14.3.2 :nth-last-child()伪类 | 3/4 |
E:first-child
| 作为其父元素第一个子元素的E元素 | § 14.3.3 :first-child伪类 | 2 |
E:last-child
| 作为其父元素最后一个子元素的E元素 | § 14.3.4 :last-child伪类 | 3 |
E:only-child
| 作为其父元素唯一子元素的E元素 | § 14.3.5 :only-child伪类 | 3 |
E:nth-of-type(n)
| 作为其类型第n个兄弟的E元素 | § 14.4.1 :nth-of-type()伪类 | 3 |
E:nth-last-of-type(n)
| 作为其类型倒数第n个兄弟的E元素 | § 14.4.2 :nth-last-of-type()伪类 | 3 |
E:first-of-type
| 作为其类型第一个兄弟的E元素 | § 14.4.3 :first-of-type伪类 | 3 |
E:last-of-type
| 作为其类型最后一个兄弟的E元素 | § 14.4.4 :last-of-type伪类 | 3 |
E:only-of-type
| 作为其类型唯一兄弟的E元素 | § 14.4.5 :only-of-type伪类 | 3 |
E F
| E元素的后代F元素 | § 15.1 后代组合器( ) | 1 |
E > F
| E元素的子元素F | § 15.2 子组合器(>) | 2 |
E + F
| 紧接在E元素之后的F元素 | § 15.3 相邻兄弟组合器(+) | 2 |
E ~ F
| 在E元素之后的F元素 | § 15.4 后续兄弟组合器(~) | 3 |
F || E
| 表示网格/表格中属于由元素F表示的列的单元格的E元素 | § 16.1 列组合器(||) | 4 |
E:nth-col(n)
| 表示属于网格/表格第n列的单元格的E元素 | § 16.2 :nth-col()伪类 | 4 |
E:nth-last-col(n)
| 表示属于网格/表格倒数第n列的单元格的E元素 | § 16.3 :nth-last-col()伪类 | 4 |
注意:部分4级选择器(上文标注为“3-UI”)是在[CSS3UI]中引入的。
3. 选择器语法与结构
3.1. 结构与术语
选择器表示树结构中特定元素模式。 选择器一词可以指简单选择器、复合选择器、复杂选择器或选择器列表。 选择器的主题 指选择器所定义的任何元素; 即任何匹配该选择器的元素。
简单选择器是针对元素的单一条件。 类型选择器、通用选择器、 属性选择器、 类选择器、ID选择器, 以及伪类都是简单选择器。 (在选择器语法中,表示为<simple-selector>。) 当某个元素被此规范定义且符合文档语言规则的简单选择器准确描述时,该元素被认为匹配该简单选择器。
复合选择器是由多个简单选择器组成的序列,彼此之间没有组合器分隔, 表示对单一元素的多重条件。 如果包含类型选择器或通用选择器, 则该选择器必须在序列开头。 序列中只允许有一个类型选择器或通用选择器。 (复合选择器在选择器语法中表示为<compound-selector>。) 当某个元素能够匹配该复合选择器中的所有简单选择器时,则认为其匹配该复合选择器。
注意:由于空格代表后代组合器, 所以在复合选择器内的简单选择器之间不允许有空格。
组合器是由两侧复合选择器表示的两个元素之间的关系条件。
选择器等级4中的组合器包括:
后代组合器(空格),
子组合器(U+003E,>
),
下一个兄弟组合器(U+002B,+
),
以及后续兄弟组合器(U+007E,~
)。
当这两个元素之间的关系条件为真时,认为其匹配该组合器。
复杂选择器是由一个或多个复合选择器通过组合器分隔而成的序列。 表示特定关系下的一组元素的多重条件, 其关系由组合器描述。 (复杂选择器在选择器语法中表示为<complex-selector>。) 当存在一组元素,每个元素都能匹配复杂选择器中对应的复合选择器, 且列表中每对连续元素之间能匹配其对应的组合器, 且最后一个元素为指定元素时,则认为该元素匹配该复杂选择器。
注意:因此,由单个复合选择器组成的选择器匹配任何满足其组成简单选择器要求的元素。 在序列前添加其他复合选择器和组合器会增加匹配约束, 因此复杂选择器的主题总是其最后一个复合选择器所表示元素的子集。
简单/复合/复杂选择器列表是由逗号分隔的简单、复合,或复杂选择器的列表。 当类型无关紧要或在周围文本中已指定,则也称为选择器列表; 如果类型重要但未指定,则默认代表复杂选择器列表。 (参见§ 4.1 选择器列表了解更多关于选择器列表的信息,以及语法中各类<*-selector-list>的正式语法。) 当某个元素能够匹配该选择器列表中任意(至少一个)选择器时,则认为其匹配该选择器列表。
3.2. 数据模型
选择器是在元素树(如DOM)上进行评估的。[DOM] 在本规范中, 这可能被称为“文档树”或“源文档”。
每个元素可能具有以下五个方面之一, 都可以作为选择条件, 并且全部作为字符串进行匹配:
- 元素类型(也称为标签名)。
- 元素的命名空间。
- ID。
- 所属的类(命名分组)。
- 属性(名称-值对)。
尽管单独元素可能没有上述任何特性, 有些元素是无特性元素。 无特性元素不会匹配任何选择器, 除非明确规定可以被匹配。 如果某个选择器允许匹配无特性元素, 匹配时必须忽略默认命名空间。[CSS3NAMESPACE]
很多选择器依赖于文档语言(即文档树的语言和语义)和/或宿主语言(即使用选择器语法的语言)的语义。 例如,:lang()选择器依赖于文档语言(如HTML) 来定义元素如何与某种语言关联。 另一个例子是,::first-line伪元素 依赖于宿主语言 (如CSS) 来定义::first-line伪元素代表什么以及其能力。
3.3. 作用域选择器
某些宿主应用可能选择将选择器限定作用域 到文档的某个子树或片段, 该作用域子树的根称为作用域根。
当选择器被限定作用域时, 它只会匹配作为作用域根的后代的元素。 (选择器的其它部分可以无限制地匹配; 只有最终的匹配元素必须在该作用域之内。)
querySelector()
方法在 [DOM] 中定义,允许作者针对其被调用的元素,评估一个 作用域限定的选择器。
像 widget
这样的调用,
只会查找
a
元素,该元素必须在 widget
元素内部,
并会忽略文档中其他
a
元素。
3.4. 相对选择器
某些上下文可能接受相对选择器, 相对选择器是表示与一个或多个相对选择器锚元素相关的元素的选择器简写。 相对选择器以组合器开头, 选择器开头隐含代表锚元素的选择器。 (如果没有组合器, 则隐含后代组合器。)
相对选择器在选择器语法中表示为<relative-selector>, 多个相对选择器列表表示为<relative-selector-list>。
3.5. 伪类
伪类是简单选择器,允许根据 文档树之外的信息进行选择, 或者表达其他简单选择器难以或无法表达的条件。 伪类也可以是动态的, 即元素在用户与文档交互时可以获得或失去伪类, 而文档本身并未改变。伪类不会出现在或修改文档源或文档树。
伪类的语法由一个“:”(U+003A 冒号) 加上该伪类的CSS标识符组成, 若为函数型伪类, 则还需一对括号包含参数。
例如,:valid是普通伪类, :lang()是函数型伪类。
所有CSS关键字一样,伪类名称是ASCII不区分大小写。 不允许在冒号与伪类名之间出现空白, 并且CSS语法中, 函数型伪类名与其左括号之间也不能有空白(因此它们构成一个CSS函数标记)。 当然,在函数型伪类括号内的参数周围可以有空白,除非另有规定。
与其他简单选择器一样,伪类允许出现在选择器包含的所有复合选择器中, 并且必须位于类型选择器或通用选择器之后(如果存在)。
注意:有些伪类是互斥的 (即包含它们的复合选择器虽然有效,但永远无法匹配任何元素), 也有一些可以同时应用于同一元素。
3.6. 伪元素
类似于某些伪类表示文档树外的附加状态信息, 伪元素 则表示文档树中未直接存在的元素。 它用于为文档树创建抽象, 超越文档树自身的能力。 例如, 伪元素可以用于选择文档的某部分, 这些部分并不对应于文档语言中的实际元素 (包括那些不与元素边界对齐或不在树结构中的范围); 或表示文档树中不存在的内容或文档树的其它投影中的内容; 或依赖于样式、布局、用户交互等未反映在文档树中的信息。
伪元素也可以代表源文档中根本不存在的内容, 如::before和::after伪元素, 它们允许在任何元素内容前后插入附加内容。
与伪类类似, 伪元素不会出现在或修改文档源或文档树。 因此,它们也不会影响结构性伪类 或其它与其原始元素或其树相关的选择器的解释。
宿主语言定义了哪些伪元素存在、类型和能力。 CSS中的伪元素分别在[CSS21](等级2)、[SELECT](等级3)和[CSS-PSEUDO-4](等级4)中定义。
3.6.1. 语法
伪元素的语法为 "::"(两个 U+003A 冒号字符), 后面跟着伪元素的名称,作为标识符。伪元素名称是ASCII 不区分大小写的。 两个冒号之间,以及冒号与名称之间都不允许有空白。
由于 CSS 等级 1 和 CSS 等级 2 将伪元素和伪类混为一谈,均采用单冒号语法, 用户代理还必须接受等级 1 和 2 伪元素的旧单冒号记法 (::before、::after、::first-line、和 ::first-letter)。 此兼容记法不能用于其他伪元素。 但由于此语法已废弃, 作者应为这些伪元素使用等级3及以上的双冒号语法。
3.6.2. 绑定到文档树
伪元素在树中并不是独立存在的: 它们总是绑定到页面上的另一个元素, 该元素称为其原始元素。 在语法上,伪元素紧跟在表示其 复合选择器之后, 该选择器用于匹配其原始元素。 如果省略了复合选择器, 则假定为通用选择器 *。
选择器 ::first-line 等价于 *::first-line, 会选择文档中每个元素的 ::first-line 伪元素。
当在选择器中遇到伪元素时, 选择器中伪元素之前的部分选择原始元素; 伪元素之后的部分(如果有)则应用于伪元素本身。 (见下文。)
3.6.3. 伪元素的伪类状态
伪元素后面可以紧跟 任意组合的用户行为伪类, 此时伪元素只有在对应状态下才会被表示。 这些伪类能否在伪元素上匹配, 取决于伪类和伪元素的定义: 除非另有说明,否则这些伪类不会在伪元素上匹配。
需明确 :not() 与 :is() 在包含上述伪类时可用。
::first-line:not(:focus) 能匹配吗?
需要注意的是,::first-line:hover 与 :hover::first-line 非常不同, 后者会匹配任何被悬停的原始元素的首行! 例如,:hover::first-line 也会在段落的第二行被悬停时,匹配该段落的首行, 而::first-line:hover 只有在首行本身被悬停时才匹配。
注意: 除非未来规范另有规定, 除用户行为伪类外,其他伪类不可与伪元素组合; 因此例如 ::before:first-child 是无效选择器。
3.6.4. 子伪元素
某些伪元素可以成为其他伪元素的原始元素, 此时这些伪元素定义为该子伪元素, 由其原始伪元素派生。 例如, 当 ::before 被赋予list-item display 类型时, 它就成为其 ::before::marker 子伪元素的原始伪元素。
如需区分, 最终原始元素 指的是真正的(非伪)元素, 伪元素即由该元素派生。
除非另一个规范明确定义了对应的子伪元素, 否则伪元素选择器不可再与其他伪元素选择器组合。 因此 ::before::before 是无效选择器, 但 ::before::marker 是有效的 (在支持 ::before::marker 子伪元素的实现中)。
3.6.5. 内部结构
某些伪元素被定义为具有内部结构。 这些伪元素后可跟随子/后代组合器, 用于表达这些关系。 伪元素之后出现组合器的选择器, 在其他情况下都是无效的。
注意:未来规范可能扩展现有伪元素的能力, 因此目前无效的某些选择器(如 ::first-line :any-link) 将来可能变为有效。
这类伪元素的子元素也可同时是其他元素的子元素。 但至少在 CSS 中,其渲染必须保证盒子树结构的树形特性。
<div> <span>foo</span> <"shadow root"> <content></content> </"shadow root"> </div>
选择器 div > span 和 div::shadow ::slotted > span 通过不同路径选中了同一个元素。
但在渲染时,
<span>
元素生成的盒子表现得像是
<content>
元素的子元素,
而不是 <div>
元素的子元素,
这样就保证了盒子树的树结构。
3.7. 字符与大小写敏感性
所有选择器语法均为ASCII 不区分大小写(即 [a-z] 和 [A-Z] 等价), 除了选择器无法控制的部分: 具体来说, 文档语言的元素名称、 属性名称、 和属性值的大小写敏感性 取决于文档语言本身。
命名空间前缀的大小写敏感性在 [CSS3NAMESPACE] 中定义。 语言范围的大小写敏感性在 :lang() 章节中定义。
空白符在选择器中包括 代码点 SPACE (U+0020)、TAB (U+0009)、LINE FEED (U+000A)、 CARRIAGE RETURN (U+000D) 和 FORM FEED (U+000C)。 其它类似空格的代码点,如 EM SPACE (U+2003) 和 IDEOGRAPHIC SPACE (U+3000) 永远不会被视为语法空白符。
选择器中的代码点可按与 CSS 相同的转义规则用反斜杠进行转义。[CSS21] 注意,转义代码点会“抵消”其在选择器中的特殊意义。
例如,选择器 #foo>a 包含一个组合器,
但 #foo\>a 则选择 id 为 foo>a
的元素。
3.8. 命名空间前缀声明
某些选择器支持命名空间前缀。 命名空间前缀声明的机制应由使用选择器的语言指定。 如果语言未指定命名空间前缀声明机制, 则不会声明任何前缀。 在 CSS 中,命名空间前缀通过 @namespace 规则声明。[CSS3NAMESPACE]
3.9. 无效选择器与错误处理
用户代理必须遵循处理无效选择器的规则:
- 选择器中出现解析错误, 例如不可识别的标记或当前解析点不允许出现的标记 (见整体§ 18 语法及各选择器语法定义), 该选择器即为无效。
- 包含未声明命名空间前缀的简单选择器为无效
- 包含无效简单选择器、无效组合器或无效标记的选择器为无效。
- 包含无效选择器的选择器列表为无效。
- 空选择器,即不包含任何复合选择器者,为无效。
注意:与 CSS 的前向兼容解析原则一致, UA 必须将所有不支持的伪类、伪元素、组合器或其他语法结构视为无效。 见部分实现。
无效选择器不代表任何内容,也不会匹配任何内容。
3.10. 历史别名
某些选择器有历史选择器别名。 这是在解析时被转换为标准名称的名称 (因此在任何表示选择器的对象模型中都不会出现此别名)。
4. 逻辑组合
4.1. 选择器列表
以逗号分隔的选择器列表表示被各个单独选择器选中的所有元素的并集(选择器列表)。 (逗号为 U+002C。)例如,在 CSS 中,当多个选择器共享同一声明时,可以将它们合并为一个逗号分隔的列表。逗号前后可以有空白。
h1 { font-family: sans-serif } h2 { font-family: sans-serif } h3 { font-family: sans-serif }
等价于:
h1, h2, h3 { font-family: sans-serif }
警告:在此示例中等价成立,是因为所有选择器均为有效选择器。如果其中有一个选择器无效,则整个选择器列表都将无效。这会使三个标题元素的样式规则全部失效,而在前一种情况下,仅有无效的选择器对应的规则失效。
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的规则被丢弃。)
4.2. 任意匹配伪类::is()
任意匹配伪类 :is(), 是一个函数型伪类,其唯一参数为 <forgiving-selector-list>。
如果参数在解析后是空列表, 此伪类有效但不匹配任何内容。 否则,该伪类匹配任何能够匹配列表中任一选择器的元素。
注意::is() 的特异性由其最特殊的参数决定。
因此,使用:is()编写的选择器,其特异性不一定等同于未用:is()时的等价选择器。例如,:is(ul, ol, .list) >
[hidden] 与 ul > [hidden], ol > [hidden], .list > [hidden],如果
ol
的子元素 [hidden],前者的特异性为 (0,2,0),后者为 (0,1,1)。详见§ 17
选择器特异性计算。
伪元素不能通过任意匹配伪类表示; 它们在 :is() 内无效。
默认命名空间声明不会影响 复合选择器在 选择器主题中的表现, 除非该复合选择器包含了 显式的通用选择器或类型选择器。
*|*:is(:hover, :focus)
而下面的选择器仅代表默认命名空间中的悬停或聚焦元素,因为在 :is() 记法中使用了显式的通用选择器:
*|*:is(*:hover, *:focus)
由于本规范早期草案使用了 :matches() 作为此伪类的名称, UA 可为向后兼容需要,将该废弃名称作为 历史选择器别名,实现为 :is()。
4.3. 否定(无匹配)伪类::not()
否定伪类 :not(), 是一个函数型伪类,参数为选择器列表。 它表示一个未被参数代表的元素。
注意:在选择器等级3中, :not() 的参数只允许为单一简单选择器。
注意::not() 的特异性由其参数中最特殊的选择器决定; 因此其行为与:not(:is(argument))完全一致。 详见§ 17 选择器特异性计算。
伪元素不能通过否定伪类表示; 它们在 :not() 内无效。
button:not([DISABLED])
以下选择器代表除 FOO 元素外的所有元素。
*:not(FOO)
以下复合选择器代表所有 HTML 元素,除了链接。
html|*:not(:link):not(:visited)
与:is()一样, 默认命名空间声明不会影响 复合选择器在 选择器主题中的表现, 除非该复合选择器包含了 显式的通用选择器或类型选择器。 (示例见:is()。)
注意::not()伪类允许编写无意义的选择器。 例如:not(*|*),表示无任何元素, 或div:not(span),与div等价但特异性更高。
4.4. 特异性调整伪类::where()
特异性调整伪类 :where(), 是一个函数型伪类, 其语法和功能与 :is() 相同。 与:is()不同,:where()伪类本身及其所有参数 都不会影响选择器的特异性——其特异性始终为零。
这有助于在选择器中引入过滤器, 同时使相关样式声明易于被覆盖。
a:not(:hover) { text-decoration: none; } nav a { /* Has no effect */ text-decoration: underline; }
但通过使用:where(),作者可以明确声明其意图:
a:where(:not(:hover)) { text-decoration: none; } nav a { /* Works now! */ text-decoration: underline; }
注意:未来的选择器等级可能会引入额外参数,以显式设置该伪类实例的特异性。
4.5. 关系伪类::has()
关系伪类,:has(), 是一个函数型伪类,参数为<forgiving-relative-selector-list>。 它表示,如果针对该元素作为锚点,有任何相对选择器能匹配至少一个元素,那么该元素会被匹配。
:has()伪类不能嵌套;:has()在:has()中是无效的。 同时,除非显式定义为:has-允许伪元素,伪元素在:has()内不是有效选择器。 (本规范未定义任何:has-允许伪元素, 但其他规范可能会定义。)
注意:通常不允许伪元素用于:has(), 因为它们的存在与祖先的样式有关, 如果允许这样查询,可能会引入循环。
<img>
子元素的<a>
元素:
a:has(> img)
下列选择器匹配紧接着另一个<dt>
元素出现的<dt>
元素:
dt:has(+ dt)
下列选择器匹配不包含任何标题元素的<section>
元素:
section:not(:has(h1, h2, h3, h4, h5, h6))
注意上述选择器中嵌套顺序很重要。 如果交换两个伪类嵌套顺序,如下:
section:has(:not(h1, h2, h3, h4, h5, h6))
...则会匹配包含任何非标题元素的<section>
元素。
5. 元素选择器
5.1. 类型(标签名)选择器
类型选择器是文档语言元素类型的名称, 表示文档树中该元素类型的实例。
类型选择器写作CSS限定名称: 即带可选命名空间前缀的标识符。[CSS3NAMESPACE](详见§ 5.3 元素选择器中的命名空间。)
5.2. 通用选择器
通用选择器是一种特殊的类型选择器, 表示任意类型的元素。
写作带有星号(*
U+002A)作为本地名的CSS限定名称。
类似于类型选择器,
通用选择器也可带命名空间限定,
仅匹配属于该命名空间的元素,
并受§ 5.3 元素选择器中的命名空间定义的默认命名空间影响。
除非元素是无特性元素, 是否包含通用选择器不会影响元素是否匹配选择器。 (无特性元素不会匹配任何选择器, 包括通用选择器。)
通用选择器遵循与其他类型选择器相同的语法规则: 每个复合选择器只能出现一次, 且必须是该复合选择器中的第一个简单选择器。
注意:某些情况下,添加通用选择器能让选择器更易读, 即使对匹配行为没有影响。 例如,div :first-child 和 div:first-child在快速浏览时不易区分, 但写作div *:first-child则更加明显。
5.3. 元素选择器中的命名空间
类型选择器和通用选择器支持可选命名空间部分:
之前已声明的命名空间前缀可加在元素名前,用命名空间分隔符“竖线”(|
U+007C)分隔。
(参见如[XML-NAMES]关于 XML 命名空间的用法。)
各种形式含义如下:
ns|E
- 命名空间 ns 中名称为 E 的元素
*|E
- 任何命名空间(包括无命名空间)中名称为 E 的元素
|E
- 无命名空间中名称为 E 的元素
E
- 若未为选择器声明默认命名空间,则等价于 *|E; 否则等价于 ns|E,其中 ns 为默认命名空间。
@namespace foo url(http://www.example.com); foo|h1 { color: blue } /* 第一条规则 */ foo|* { color: yellow } /* 第二条规则 */ |h1 { color: red } /* ...*/ *|h1 { color: green } h1 { color: green }
第一条规则(不计@namespace规则) 只匹配命名空间为 "http://www.example.com" 的h1元素。
第二条规则匹配 "http://www.example.com" 命名空间中的所有元素。
第三条规则只匹配无命名空间的h1元素。
第四条规则匹配任何命名空间(包括无命名空间)中的h1元素。
最后一条规则等价于第四条,因为未定义默认命名空间。
如果声明了默认命名空间,则复合选择器中未包含类型选择器的部分, 仍只会匹配该默认命名空间中的元素。
@namespace url("http://example.com/foo"); .special { ... }
.special选择器只会匹配命名空间为 "http://example.com/foo" 的元素, 即使没有出现类型名(与 DOM 中命名空间配对)。
如果类型选择器或通用选择器包含未声明的命名空间前缀,则为无效选择器。
5.4. 定义伪类::defined
在某些宿主语言中, 元素可能区分“已定义/已构造”与未定义。 :defined 伪类用于匹配已完全定义的元素, 具体由宿主语言规定。
如果宿主语言没有这种区分, 其中所有元素都匹配:defined。
p : defined{ ...}
自定义元素则最初是未定义的, 只有在正确注册后才变为已定义。 这意味着:defined伪类 可用于在自定义元素注册前隐藏它:
custom-element { visibility: hidden }
custom-element:defined { visibility: visible }
6. 属性选择器
选择器可以表示元素的属性。当选择器用于匹配元素的表达式时, 属性选择器 只要元素具有与属性选择器所表示属性匹配的属性,就应视为匹配该元素。
是否要为多值匹配添加逗号分隔语法?如 [rel ~= next, prev, up, first, last]
6.1. 属性存在与值选择器
CSS2 引入了四种属性选择器:
- [att]
- 表示具有
att
属性的元素, 属性值为任意值。 - [att=val]
- 表示具有
att
属性, 且属性值正好为 "val" 的元素。 - [att~=val]
- 表示具有
att
属性, 属性值为空白符分隔的单词列表,其中之一正好为 "val"。 如果 "val" 包含空白符, 永远不会匹配任何内容 (因为单词是用空格分隔的)。 若 "val" 是空字符串, 也不会匹配任何内容。 - [att|=val]
- 表示具有
att
属性的元素, 属性值要么正好为 "val",要么以 "val" 开头且后跟 "-" (U+002D)。 主要用于语言子码匹配 (如 HTML 的hreflang
属性) 详见 BCP 47 ([BCP47]) 或其后继规范。 关于lang
(或xml:lang
)语言子码匹配, 参见:lang()伪类。
属性值必须为<ident-token>或<string-token>。[CSS3SYN]
以下属性选择器表示带有title
属性的h1元素,
属性值任意:
h1[title]
下例中,选择器表示class
属性值正好为 "example" 的span元素:
span[class="example"]
可以使用多个属性选择器同时表示一个元素的多个属性,
或对同一属性的多个条件。如下选择器表示hello
属性值正好为 "Cleveland",
且goodbye
属性值正好为 "Columbus" 的span元素:
span[hello="Cleveland"][goodbye="Columbus"]
以下 CSS 规则演示 "=" 与 "~=" 的区别。第一个选择器可匹配 a 元素,其 rel
属性值为 "copyright copyleft
copyeditor"。第二个选择器仅匹配 a 元素,且 href
属性值正好为 "http://www.w3.org/"。
a[rel~="copyright"] { ... } a[href="http://www.w3.org/"] { ... }
以下选择器表示hreflang
属性值正好为 "fr" 的a元素。
a[hreflang=fr]
以下选择器表示hreflang
属性值以 "en" 开头的a元素,包括 "en"、"en-US"、"en-scouse":
a[hreflang|="en"]
以下选择器表示DIALOGUE元素,
只要其 character
属性值为 romeo 或 juliet 之一:
DIALOGUE[character=romeo] DIALOGUE[character=juliet]
6.2. 子串匹配属性选择器
另外提供了三种属性选择器,用于匹配属性值中的子串:
- [att^=val]
- 表示具有
att
属性,且属性值以前缀 "val" 开头的元素。 如果 "val" 是空字符串, 则该选择器不会匹配任何内容。 - [att$=val]
- 表示具有
att
属性,且属性值以后缀 "val" 结尾的元素。 如果 "val" 是空字符串, 则该选择器不会匹配任何内容。 - [att*=val]
- 表示具有
att
属性,且属性值中至少包含一次子串 "val" 的元素。 如果 "val" 是空字符串, 则该选择器不会匹配任何内容。
属性值必须为<ident-token>或<string-token>。
object[type^="image/"]
下列选择器表示一个 HTML a 元素,
其 href
属性值以 ".html" 结尾。
a[href$=".html"]
下列选择器表示一个 HTML 段落,
其 title
属性值中包含子串 "hello"
p[title*="hello"]
6.3. 大小写敏感性
属性名称和值的大小写敏感性默认取决于文档语言。
如需无视文档语言规则,以ASCII 不区分大小写方式匹配属性值,
可在属性选择器闭合括号(]
)前添加标识符 i
。
当出现该标志时,
UA 必须以ASCII 不区分大小写方式匹配属性值(即 [a-z] 和 [A-Z] 等价)。
或可在属性选择器闭合括号前添加标识符 s
;
此时 UA 必须以大小写敏感方式匹配值,
采用“完全相同”语义[INFRA],
无视文档语言规则。
与选择器语法其它部分一样,
i
和 s
标识符本身也是ASCII
不区分大小写的。
frame
属性值为 hsides
的元素设置样式,无论值为 hsides
、HSIDES
、hSides
等等,
即使在 XML 环境下属性值应区分大小写也能匹配。
[frame=hsides i] { border-style: solid none; }
type="a"
的列表样式与 type="A"
区分开,即使 HTML 定义 type
属性为不区分大小写。
[type="a" s] { list-style: lower-alpha; } [type="A" s] { list-style: upper-alpha; }
注意:部分文档模型在解析时会规范化不区分大小写的属性值,
使得无法进行大小写敏感匹配。
通过 s
标志进行大小写敏感匹配仅在保留原始大小写的系统中有效。
6.4. 属性选择器与命名空间
属性选择器中的属性名称为CSS限定名称:已声明的命名空间前缀可加在属性名前,用竖线(|
)分隔。遵循 XML
命名空间推荐,默认命名空间不适用于属性,因此无命名空间部分的属性选择器仅匹配无命名空间的属性(等价于 |attr)。命名空间前缀为星号时,表示选择器要匹配所有属性名,无论属性命名空间如何。
属性名称带未声明命名空间前缀的属性选择器为无效选择器。
@namespace foo "http://www.example.com"; [foo|att=val] { color: blue } [*|att] { color: yellow } [|att] { color: green } [att] { color: green }
第一条规则只匹配属性 att
属于 "http://www.example.com" 命名空间且值为 "val" 的元素。
第二条规则只匹配属性 att
的元素,无论属性命名空间(包括无命名空间)。
最后两条规则等价,只匹配属性 att
没有命名空间的元素。
6.5. DTD中的默认属性值
属性选择器表示文档树中的属性值。 文档树的构建方式不在选择器规范范围内。 某些文档格式中可以在 DTD 或其他地方定义默认属性值,但只有当这些值出现在文档树中时,属性选择器才能选中。选择器应设计为无论默认值是否包含在文档树中都能正常工作。
例如,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.6. 类选择器
类选择器由一个句点(.
U+002E)紧跟标识符给出,表示元素属于由该标识符标识的类,具体由文档语言定义。例如,在[HTML5]、[SVG11] 和 [MATHML]中,
类归属由 class
属性决定:在这些语言中,等价于本地 class
属性上的 ~=
记法
(即 [class~=identifier]
)。
可如下为所有 class~="pastoral"
的元素指定样式:
*.pastoral { color: green } /* 所有 class~=pastoral 的元素 */
或直接写:
.pastoral { color: green } /* 所有 class~=pastoral 的元素 */
下例仅为 class~="pastoral"
的 H1 元素指定样式:
H1.pastoral { color: green } /* H1 元素且 class~=pastoral */
根据这些规则,下方第一个 H1
实例不会变为绿色,第二个则会:
<H1>Not green</H1> <H1 class="pastoral">Very green</H1>
下例规则会匹配所有 P 元素,其 class
属性是一个以空白分隔的值列表,包含 pastoral
和
marine
:
p.pastoral.marine { color: green }
该规则在 class="pastoral blue aqua
marine"
时匹配,在 class="pastoral
blue"
时不匹配。
注意:由于 CSS 赋予“class”属性很强的能力,作者可设计几乎无结构表现的“文档语言”(如 HTML 的 div 和 span), 并仅通过“class”属性指定样式。作者应避免此做法,因为文档语言的结构性元素常有公认含义,作者自定义类可能没有。
注意:若元素有多个 class 属性,匹配前应将各值用空格拼接。目前工作组不认为会出现这种情况,因此规范对此行为为非规范性。
如匹配启用怪异模式的文档, 类名必须ASCII 不区分大小写匹配; 否则类选择器为区分大小写,只匹配完全一致的类名。[INFRA]
6.7. ID选择器
文档语言中可以有声明为ID类型的属性。
ID类型属性的特殊之处在于,在合规文档中,所有此类属性的值不能重复,
不论其所在元素类型;
无论何种文档语言,ID类型属性可用于唯一标识其元素。
在HTML中所有ID属性都叫id
;
XML应用可使用不同命名,但约束一致。
元素哪个属性被视为“ID属性”由文档语言定义。
ID选择器由“井号”(U+0023,#
)紧跟ID值组成,
ID值必须是CSS标识符。
ID选择器表示具有与选择器中标识符一致的ID的元素实例。
(在不合规文档中,可能有多个元素匹配同一ID选择器。)
h1#chapter1
下列ID选择器表示ID类型属性值为"chapter1"的任意元素:
#chapter1
下列选择器表示ID类型属性值为"z98y"的任意元素。
*#z98y
注意:在XML 1.0 [XML10]中,元素的ID属性信息在DTD或schema中定义。 解析XML时,UA未必读取DTD,因此可能无法确定元素ID(但UA可以有命名空间相关知识来确定)。 若样式作者知道或怀疑UA无法确定元素ID,应用普通属性选择器: ''[name=p371] 代替 #p371''。
若元素有多个ID属性,从选择器角度都应作为该元素的ID处理。此情况可能由xml:id、DOM3 Core、XML DTD和命名空间知识混合导致。
如匹配启用怪异模式的文档, ID必须ASCII不区分大小写匹配; 否则ID选择器区分大小写,只匹配完全一致的ID。[INFRA]
7. 语言伪类
7.1. 方向性伪类::dir()
:dir()
伪类允许作者基于文档语言确定的方向性编写选择器。
例如[HTML5]定义了如何确定元素方向性,
基于dir
属性、周围文本等因素。
另如国际化标签集[ITS20]中的its:dir
和dirRule
元素可在[XML10]中定义方向性。
:dir()伪类不会依据样式状态选中元素——比如CSS的direction属性不会影响其匹配。
伪类:dir(ltr)表示方向性为左到右(ltr
)的元素。伪类:dir(rtl)表示方向性为右到左(rtl
)的元素。:dir()参数必须为单一标识符,否则选择器无效。标识符与括号间可选空白。除ltr
和rtl
外的值不会无效,但不会匹配任何内容。(如未来规范定义其他方向性,Selectors可扩展支持。)
:dir(C)与''[dir=C]''的区别在于后者只对元素的属性值做比较,而前者利用UA对文档语义的了解做比较。例如HTML中,方向性会继承,子元素没有dir
属性时会继承最近祖先的dir
属性。再如HTML中,元素匹配''[dir=auto]''会根据内容解析匹配:dir(ltr)或:dir(rtl)。[HTML5]
7.2. 语言伪类::lang()
如果文档语言指定了如何确定一个元素的(人类)内容语言, 就可以编写选择器,根据其内容语言来选择元素。 :lang() 伪类, 接受一个或多个以逗号分隔的语言范围, 表示其内容语言为参数列出的语言之一的元素。 :lang()中的每个语言范围 必须是有效的CSS<ident>或<string>。 (因此,包含星号的语言范围必须正确转义或用字符串括起来, 例如 :lang(\*-Latn) 或 :lang("*-Latn")。)
注意:元素的内容语言由文档语言定义。
例如,在 HTML [HTML5] 中,内容语言由 lang
属性、
meta 元素中的信息,
以及协议(如 HTTP 头)共同决定。
XML 语言可以使用 xml:lang
属性来为元素指示语言信息。 [XML10]
一个元素的内容语言如果在BCP 47语法下 [BCP47],
在 [RFC4647] 语言标签匹配 (第3.3.2节)
规定的扩展过滤操作中
匹配该语言范围,
则算匹配。
对此,通配符语言范围("*"
)
不会匹配语言未标记的元素(如 lang=""
),
但会匹配语言标记为不确定(lang=und
)的元素。
匹配过程采用ASCII不区分大小写方式。
执行比较时,不要求语言范围是有效的语言代码。
由空字符串组成的语言范围 (:lang("")) 只会匹配语言未标记的元素。
注意:建议文档和协议使用 [BCP47] 或其后继标准的代码来指示语言,
XML 格式建议用 xml:lang
属性指示语言。[XML10] 参见 “FAQ: 使用两位还是三位语言代码?”
html:lang(fr-be) html:lang(de) :lang(fr-be) > q :lang(de) > q
注意::lang(C)与''|=''操作符的区别在于后者只对元素属性做比较,而:lang(C)利用UA对文档语义的了解做比较。
<body lang=fr> <p>Je suis français.</p> </body>
如:lang(de-DE)可匹配de-DE、de-DE-1996、de-Latn-DE、de-Latf-DE、de-Latn-DE-1996, 而''[lang|=de-DE]仅匹配 de-DE''和de-DE-1996。
如需对主语言子标签通配符匹配,应使用星号:*-CH可匹配de-CH、it-CH、fr-CH和rm-CH。
如需用此类型的语言范围匹配元素lang属性值, 可同时用属性选择器和语言伪类, 如[lang]:lang(de-DE)。
注意:通配符语言匹配与逗号分隔列表是4级新增功能。
8. 位置伪类
8.1. 超链接伪类::any-link
:any-link
伪类表示作为超链接源锚点的元素。
例如,在[HTML5]中,
任何
a
或
area
元素带有
href
属性时即为超链接,
因此匹配 :any-link
。
当元素能匹配 :link 或 :visited 时,
即等价于 :is(:link, :visited)。
8.2. 链接历史伪类::link 和 :visited
用户代理通常会将未访问过的超链接与已访问过的超链接显示为不同样式。选择器 提供了伪类 :link 和 :visited 用于区分:
经过一段时间后,用户代理可能会将已访问链接恢复为(未访问的):link状态。
这两种状态是互斥的。
由于样式表作者有可能滥用 :link 和 :visited 伪类来判断用户访问过哪些网站而未经同意, UA 可将所有链接视为未访问或采取其他措施, 在保持已访问与未访问链接样式差异的同时保护用户隐私。
8.3. 本地链接伪类::local-link
:local-link伪类 允许作者根据用户在站点中的当前位置为超链接设置样式。 它表示作为超链接源锚点的元素,且目标绝对URL与元素自身文档URL相同。 若链接目标包含片段URL, 则当前URL片段也必须一致; 若不一致,则比较时不考虑片段URL部分。
注意:页面的当前URL可能因用户操作(如点击指向同一页面不同片段的链接)、
或使用 pushState
API 变化,
以及跳转至不同页面或重定向(可由HTTP、<meta http-equiv="...">
、
或脚本指令等发起)等情况而变化。
UA 必须确保 :local-link、
以及下方的 :target 和
:target-within 伪类,
能正确响应所有此类状态变化。
8.4. 目标伪类::target
在某些文档语言中, 文档URL还能进一步指向文档内的特定元素, 通过URL的片段实现。 被这样指向的元素即为文档的目标元素。
https://example.com/index.html#section2
指向https://example.com/index.html
文档中的id="section2"
的元素。
:target 伪类匹配文档的目标元素。 若文档URL无片段标识,则文档无目标元素。
:target { color : red } :target::before { content : url(target.png) }
8.5. 目标容器伪类::target-within
:target-within伪类 适用于任意能匹配 :target 伪类的元素, 以及在扁平树(包括文本节点等非元素节点)中 有后代元素满足 :target 匹配条件的元素。
8.6. 参考元素伪类::scope
在某些情况下,选择器是相对于一个或多个 作用域根 匹配的,
例如在 [DOM] 中调用 querySelector()
方法时。
:scope
伪类用于表示
这个 作用域根,
其可以是真实的元素,
也可以是虚拟元素(如 DocumentFragment
)。
若没有作用域根, :scope表示文档根元素 (等价于 :root)。 若规范希望该伪类仅匹配特定元素而非文档根, 必须定义其作用域根。
虚拟作用域根是表示文档片段根的对象, 可用于选择器模式中表示其它元素与该作用域根的关系, 作为其所代表文档片段中任何根元素的父节点。 虚拟作用域根为无特性元素,不能作为选择器主题。
DocumentFragment
df
,
那么 df. querySelectorAll( ":scope > .foo" )
匹配文档片段中“顶层”的所有 .foo 元素
(即它们的 parentNode
为该文档片段)。
但 df
不会匹配任何内容,
因为文档片段本身不能作为选择器主题。
9. 用户操作伪类
交互式用户界面有时会根据用户操作更改渲染效果。 选择器提供了多个用户操作伪类用于选择用户正在操作的元素。 (在非交互式用户代理中,这些伪类有效但永不匹配任何元素。)
这些伪类不是互斥的。 一个元素可以同时匹配多个此类伪类。
a:link /* 未访问链接 */ a:visited /* 已访问链接 */ a:hover /* 用户悬停 */ a:active /* 激活链接 */
动态伪类组合示例:
a:focus a:focus:hover
最后一个选择器匹配同时处于 :focus 和 :hover 状态的a 元素。
注意:用于判断本节定义的伪类何时生效所需的点击测试细节尚未定义,未来将补充。
9.1. 指针悬停伪类::hover
:hover 伪类在用户用指针设备指向某元素时生效, 但不一定激活该元素。 例如,视觉用户代理可在鼠标悬停于元素生成的盒子上时应用此伪类。 无法因硬件限制侦测悬停的交互式用户代理(如无法侦测悬停的笔设备)仍合规; 此选择器在这类UA中永不匹配。
若元素的某个后代在扁平树(包括文本节点等非元素节点)中满足上述条件,元素也匹配:hover。
文档语言可定义元素可匹配:hover的其他方式。
例如,[HTML5]定义了当其标签元素被悬停时,控制元素匹配:hover
。
注意:由于:hover状态可因子元素被指针设备指向而生效, 所以:hover可能应用于并非指针设备下方的元素。
:hover 伪类可应用于任意伪元素。
9.2. 激活伪类::active
:active 伪类在元素被用户激活时生效。例如在用户按下鼠标按钮和松开之间。若有多个鼠标按钮,:active仅应用于主激活按钮(通常为“左键”),及其别名。
哪些元素可成为:active可能受文档语言或实现限制。 例如,[HTML5]定义了可激活元素列表。
若元素的某个后代在扁平树(包括文本节点等非元素节点)中满足上述条件,元素也匹配:active。
文档语言可定义元素可匹配:active的其他方式。
注意:元素可同时为:visited和:active(或:link和:active)。
9.3. 输入焦点伪类::focus
:focus 伪类在元素具有焦点时生效 (可接受键盘、鼠标或其他输入事件)。
哪些元素可获得:focus可能受文档语言或实现限制。 例如,[HTML]定义了可聚焦区域列表。
文档语言可定义元素可匹配:focus的其他方式, 但:focus伪类不得自动传递到父元素——如需对父元素匹配,请用:focus-within。 (如因其他机制导致传递到父元素亦可生效,但不能仅因是父元素就生效。)
作者希望能将:focus从表单控件传递到其关联的label
元素;
主要反对意见是实现难度。
见CSSWG议题(CSS)和WHATWG议题(HTML)。
9.4. 可见焦点伪类::focus-visible
虽然:focus 伪类始终匹配当前获得焦点的元素, UA只有在某些情形下才会显示焦点(如画出“焦点环”), 而是用各种启发式方法,仅在用户最需要时才显示焦点。 :focus-visible 伪类 仅在这些情形下匹配获得焦点的元素, 允许作者更改焦点指示器的样式, 而不会改变焦点指示器出现的时机。
:root{ --focus-gold : #ffbf47; } :focus-visible{ outline : 3 px solidvar ( --focus-gold); } a:focus-visible{ background-color : var ( --focus-gold); }
用户代理也应用:focus-visible指定默认焦点样式, 这样作者使用:focus-visible时无需同时禁用默认:focus样式。
9.5. 焦点容器伪类::focus-within
:focus-within伪类 应用于自身可匹配:focus伪类的元素, 以及其在扁平树(包括文本节点等非元素节点)中的后代可匹配:focus的元素。
10. 时间维度伪类
这些伪类用于根据当前在某个时间线上的显示或活动位置对元素进行分类,如文档的语音渲染期间,或使用 WebVTT 渲染字幕的视频播放期间。
CSS 未定义此时间线; 必须由宿主语言定义。 如果元素未定义时间线, 则这些伪类不得匹配该元素。
注意: :current元素的祖先同样会是:current, 但:past或:future元素的祖先不一定也会是:past或:future。 一个元素至多只能匹配:current、:past或:future之一。
10.1. 当前元素伪类::current
:current 伪类表示当前显示的元素或其祖先。
其另一形式:current(),类似:is(), 接受一个复合选择器列表作为参数:它表示能够匹配参数的:current元素,如果无法匹配,则表示能够匹配参数的:current元素的最内层祖先。 (如果:current元素及其祖先都无法匹配参数,则选择器不代表任何内容。)
10.2. 过去元素伪类::past
:past 伪类表示所有被定义为完全在:current元素之前出现的元素。 例如,WebVTT规范定义了:past伪类相对于媒体元素当前播放位置。 如果文档语言未定义基于时间的元素顺序, 则表示所有作为:current元素(可能是间接)前一个同级的元素。
10.3. 未来元素伪类::future
:future 伪类表示所有被定义为完全在:current元素之后出现的元素。 例如,WebVTT规范定义了:future伪类相对于媒体元素当前播放位置。 如果文档语言未定义基于时间的元素顺序, 则表示所有作为:current元素(可能是间接)后一个同级的元素。
11. 资源状态伪类
本节中的伪类适用于表示已加载资源的元素, 特别是图片/视频, 允许作者根据其状态的某些特性选择这些元素。
11.1. 媒体播放状态::playing、:paused 和 :seeking 伪类
:playing 伪类表示能够“播放”或“暂停”的元素, 当该元素处于“播放”状态时匹配。 (包括元素正在播放, 以及因某些非用户原因暂时停止但会自动恢复的状态, 如“缓冲中”或“卡顿”状态。)
:paused 伪类表示能够“播放”或“暂停”的元素, 当该元素处于“暂停”(即未“播放”)状态时匹配。 (包括明确的“暂停”状态, 以及其他非播放状态,如“已加载但尚未激活”等。)
:seeking
伪类表示能够“搜索”进度的元素,
当元素处于“搜索”状态时匹配。
(关于
audio
和
video
的详细说明,参见 HTML
§ 4.8.11.9 搜索。)
11.2. 媒体加载状态::buffering 和 :stalled 伪类
:buffering 伪类表示能够“播放”或“暂停”的元素, 当该元素因正在主动获取媒体数据但尚未获得足够数据以恢复播放, 无法继续播放时匹配。 (注意,元素“缓冲中”时仍视为“播放”状态。 任何匹配:buffering的元素,也会匹配:playing。)
:stalled
伪类表示元素因正在主动获取媒体数据但在一段时间内未收到任何数据,
无法继续播放时匹配。
关于
audio
和
video
元素,
此时间长度即媒体元素卡顿超时。[HTML](注意,同:buffering伪类一样,
元素“卡顿”时仍视为“播放”状态。
任何匹配:stalled的元素,也会匹配:playing。)
11.3. 声音状态::muted 和 :volume-locked 伪类
:muted
伪类表示能够产生声音的元素,
当该元素处于“静音”(强制静音)状态时匹配。
(关于
audio
和
video
元素,参见muted。[HTML])
:volume-locked 伪类表示能够产生声音的元素, 当以编程方式改变元素音量时, 该元素的有效媒体音量不会发生改变时匹配。
12. 元素显示状态伪类
12.1. 折叠状态::open 和 :closed 伪类
:open 伪类表示具有“打开”与“关闭”状态的元素, 且当前处于“打开”状态。
:closed 伪类表示具有“打开”与“关闭”状态的元素, 且当前处于关闭状态。
“打开”和“关闭”的具体含义取决于宿主语言,
例如 HTML 的
details
、
select
、
以及
dialog
元素,
都可以切换为“打开”以显示更多内容
(对于dialog
元素,甚至是显示任意内容)。
注意:“打开”或“关闭”是语义状态。 即使元素当前未显示 (例如设置了visibility: collapse, 或属于display: none的子树), 也可以是“打开”的,并会匹配:open。
12.2. 模态(独占交互)状态::modal 伪类
:modal 伪类表示处于排除与外部元素交互状态的元素, 直到该元素被关闭。 多个元素可同时为:modal, 但仅有一个处于活动状态(可接收输入)。
dialog
元素通过 showModal()
API 打开时即为:modal。
类似地,通过 requestFullscreen()
API 打开的:fullscreen元素也为:modal,
因为这会阻止与页面其余部分的交互。
12.3. 全屏展示状态::fullscreen 伪类
:fullscreen伪类表示 以占据大部分(通常全部)屏幕模式显示的元素, 例如由全屏API定义的模式。[FULLSCREEN]
12.4. 画中画展示状态::picture-in-picture 伪类
:picture-in-picture伪类表示 以占据大部分(通常全部)视口模式显示的元素, 其视口限制在屏幕部分区域, 并在其他内容之上显示, 例如使用画中画API时。[picture-in-picture]
13. 输入伪类
本节中的伪类主要用于获取用户输入的元素, 例如 HTML 的 input 元素。
13.1. 输入控件状态
13.1.1. :enabled 与 :disabled 伪类
:enabled 伪类表示 处于启用状态的用户界面元素; 这些元素必须有对应的禁用状态。
相反,:disabled 伪类表示 处于禁用状态的用户界面元素; 这些元素必须有对应的启用状态。
什么是启用状态、禁用状态以及用户界面元素取决于宿主语言。在典型文档中,大多数元素既不是 :enabled 也不是 :disabled。 例如,[HTML5] 将 非禁用交互元素视为 :enabled, 而明确 禁用的此类元素为 :disabled。
注意:可能影响用户与某个用户界面元素交互能力的 CSS 属性不会影响该元素是否匹配 :enabled 或 :disabled;例如 display 和 visibility 属性不会影响元素的启用/禁用状态。
13.1.2. 可变性伪类::read-only 与 :read-write
若元素可被用户修改(由文档语言定义),则匹配 :read-write。 否则为 :read-only。
例如,在 [HTML5] 中,非禁用且非只读的
<input>
元素 为 :read-write,
有 contenteditable
属性且为 true 的元素也是如此。
13.1.3. 占位符显示伪类::placeholder-shown
输入元素有时会显示占位符文本,
用于提示用户输入内容。
例如 [HTML5] 的 placeholder
属性。
:placeholder-shown 伪类
匹配显示此类占位符文本的输入元素,
无论该文本由属性、真实元素给定,或由 UA 隐式显示。
placeholder
属性在
input
元素上
提供占位符文本,
option
元素作为
select
的首项在特定条件下也可以。
只要显示了占位符文本,即应用 :placeholder-shown 类。
13.1.4. 自动输入伪类::autofill
:autofill 伪类表示被用户代理自动填充且尚未被用户修改的输入元素。
13.1.5. 默认项伪类::default
:default 伪类用于一组类似元素中为默认项的一个或多个 UI 元素。通常用于 上下文菜单项、按钮以及选择列表/菜单。
例如,在一组按钮中默认的提交按钮,
或弹出菜单中的默认选项。
多选组(如披萨配料)中可有多个元素匹配 :default。
例如 [HTML5] 规定 :default 匹配 表单中的“默认按钮”、
<select>
中的初始选中<option>
,以及其它元素。
13.2. 输入值状态
13.2.1. 选中项伪类::checked
单选框和复选框元素可由用户切换。
某些菜单项在用户选择时会“被选中”。
当这些元素被切换为“开启”时,
应用 :checked
伪类。
例如 [HTML5] 规定 已选中复选框、单选按钮和选中的
<option>
元素 匹配 :checked。
:checked
伪类是动态的,
可被用户操作更改,
但也可由文档中的语义属性(如 selected
和 checked
属性)决定,
因此适用于所有媒体。
13.2.2. 未定值伪类::indeterminate
:indeterminate 伪类用于值处于不确定状态的 UI 元素。 例如,单选框和复选框既可被选中也可未选中, 但有时会处于既非选中也非未选中的未定状态。 进度条在完成百分比未知时也可处于未定状态。 [HTML5] 规定 复选框 如何匹配 :indeterminate。
与 :checked 伪类类似,:indeterminate 适用于所有媒体。 例如,未预选项的单选组成员即使在静态展示中也为 :indeterminate。
13.3. 输入值校验
13.3.1. 空值伪类::blank
:blank 伪类 用于输入值为空(即空字符串或无输入)的用户输入元素。
textarea
内容为空,
或
input
字段值为空。
注意这里考虑的是提交时的值
(见 表单控件的值,[HTML]),
在 HTML 中不一定等同于元素的
value
属性值。
注意:此选择器有被废弃风险。
13.3.2. 有效性伪类::valid 与 :invalid
当元素的内容或值根据文档语言定义的数据有效性语义(如 [XFORMS11] 或 [HTML5])分别为有效或无效时,元素为 :valid 或 :invalid。 无数据有效性语义的元素既不是 :valid 也不是 :invalid。
注意:无约束的元素通常总是 :valid,
而无数据有效性语义的元素则既不是 :valid 也不是 :invalid。
例如 HTML 的 <input type="text">
元素可能无约束,
但 p 元素没有有效性语义,
因此永远不匹配这两个伪类。
13.3.3. 范围伪类::in-range 与 :out-of-range
:in-range 和 :out-of-range 伪类 仅适用于有限制范围的元素。若元素绑定的值在其文档语言定义的范围内或超出范围,则分别为 :in-range 或 :out-of-range。 无数据范围限制或不是表单控件的元素既不是 :in-range 也不是 :out-of-range。 例如,值为 11 的滑块元素,若控件只允许 1-10,则为 :out-of-range。另如菜单元素值为 "E",但弹出菜单仅有 "A"、"B"、"C" 选项。
13.3.4. 可选性伪类::required 与 :optional
表单元素在其所属表单有效提交前,若值为必填则为 :required,若值为可选则为 :optional。 非表单元素既不是必填也不是可选。
13.3.5. 用户交互伪类::user-valid 与 :user-invalid
:user-invalid 和 :user-valid 伪类 分别表示用户输入错误或正确,但仅在用户已显著交互后生效。
:user-invalid 伪类 必须在用户尝试提交表单后且在再次交互前, 匹配 :invalid、:out-of-range 或 必填但:required且内容为空的元素。
:user-valid 伪类必须在用户尝试提交表单后且在再次交互前, 匹配 :valid 元素。
用户代理可允许这些伪类在其他时机匹配元素, 如用于高亮错误。例如,UA 可以选择在用户输入内容并切换焦点后,就让 :user-invalid 匹配 :invalid 元素,且仅在用户成功纠正输入后停止匹配。
<form> <label> Volume: <input name='vol' type=number min=0 max=10 value=11> </label> ... </form>
与 :-moz-ui-invalid 对比。
评估 :dirty 伪类建议
明确说明本伪类(以及 :invalid/:valid)可用于 form 和 fieldset 元素。
14. 树结构伪类
选择器引入了结构性伪类的概念,以便根据文档树中额外的信息进行选择,而这些信息无法通过其他简单选择器或组合器表示。
在计算元素在其父元素的子元素列表中的位置时,独立文本和其他非元素节点不计入索引。在计算元素在其父元素的子元素列表中的位置时,索引编号从 1 开始。
14.1. :root 伪类
:root 伪类表示文档的根元素。
例如,在一个 DOM 文档中, :root 伪类将匹配 Document 对象的根元素。 在 HTML 中,这将是 html 元素 (除非脚本已用于修改文档)。
14.2. :empty 伪类
:empty 伪类表示 没有子元素的元素, 除了可以有文档中的空白字符。 在文档树中, 只有元素节点和内容节点 (比如[DOM]文本节点和实体引用) 其数据长度大于零时才需计入元素非空状态; 注释、处理指令和其他节点 不应影响元素是否被视为空。
p
元素的有效表示方式:
<p></p> <p> <p> </p> <p></p>
div:empty 不是以下片段中 <div>
元素的有效表示方式:
<div>text</div> <div><p></p></div> <div> </div> <div><p>bla</p></div> <div>this is not <p>:empty</p></div>
注意:在 Selectors 的 Level 2 和 Level 3 中,:empty 不会匹配仅包含空白的元素。 这一点已被修改,即——鉴于空白在 HTML 中大多会被折叠, 且常用于源代码格式化, 尤其是省略结束标签的元素容易吸收这些空白到其 DOM 文本内容中—— 作者认为为空的元素可以通过此选择器选中,正如他们所预期的那样。
14.3. 子元素索引伪类
本节定义的伪类根据元素在其包含型兄弟节点中的索引选择元素。
注意:Selectors 3 描述这些选择器是根据元素在其父元素的子列表中的索引进行选择的。 (这种描述仍体现在本节名称和多个伪类名称中。) 由于没有理由排除它们匹配无父元素或父元素不是元素的情况, 所以现在改用元素在其兄弟节点中的相对索引进行表述。
14.3.1. :nth-child() 伪类
:nth-child(An+B [of S]? ) 伪类表示 元素在 An+B 的索引位置, 该列表由其包含型兄弟节点,且与选择器列表 S 匹配的元素组成, S 是 <complex-selector-list>,并作为宽容选择器列表解析。 如果省略 S,则默认值为 *|*。
An+B 表达式及其解释 在CSS Syntax 3 § 6 An+B 微语法中定义; 它表示任何索引 i = An + B,其中 n 为任意非负整数。
注意:在此情况下,元素列表是从 1 开始编号的;
即某元素的第一个子元素索引为 1,并且会被 :nth-child(2n+1) 匹配,
因为当 n=0
时表达式的结果为 1。
例如,该选择器可以用于选中表格的每隔一行, 也可以用于实现四种循环的段落文本颜色交替。
:nth-child(even) /* 代表第 2、4、6... 个元素 */ :nth-child(10n-1) /* 代表第 9、19、29... 个元素 */ :nth-child(10n+9) /* 同上 */ :nth-child(10n+-1) /* 语法无效,会被忽略 */
注意::nth-child() 伪类的特异性 为单个伪类的特异性加上 (如果指定了 S) S 中最具体的复杂选择器的特异性。 参见 § 17 计算选择器的特异性。 因此 S:nth-child(An+B) 和 :nth-child(An+B of S) 特异性完全相同, 但行为不同 (见下例)。
:nth-child(-n+3 of li.important)
注意这与将选择器放到函数外不同,例如:
li.important:nth-child(-n+3)
这个选择器只会选中前三个子元素, 如果它们同时是“important”列表项。
通常,给表格行设置斑马条纹,作者会使用如下 CSS:
tr { background: white; } tr:nth-child(even) { background: silver; }
但如果有些行被隐藏且未显示, 可能会破坏该模式, 导致多个相邻行有相同背景色。 假设用 [hidden] 属性在 HTML 中隐藏行, 以下 CSS 可实现稳健的斑马条纹效果, 无论哪些行被隐藏,都能保持正确的交替背景:
tr { background: white; } tr:nth-child(even of :not([hidden])) { background: silver; }
14.3.2. :nth-last-child() 伪类
:nth-last-child(An+B [of S]? ) 伪类表示 元素在 An+B 的索引位置, 该列表由其包含型兄弟节点,且与选择器列表 S 匹配的元素组成, 从末尾反向计数。S 是 <complex-selector-list>,并作为宽容选择器列表解析。 如果省略 S,则默认值为 *|*。
注意::nth-last-child() 伪类的特异性, 与:nth-child()伪类一样, 是常规伪类的特异性加上选择器参数 S 的特异性。 参见 § 17 计算选择器的特异性。
CSS Syntax 模块[CSS3SYN]定义了An+B 表达式。
tr:nth-last-child(-n+2) /* 代表 HTML 表格最后两行 */ foo:nth-last-child(odd) /* 代表其父元素中,倒数第一个开始的所有奇数 foo 元素 */
14.3.3. :first-child 伪类
:first-child 伪类 表示元素在其包含型兄弟节点中为第一个。 等同于 :nth-child(1)。
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 是任何元素的第一个子元素 */ a:first-child /* 同上(假设 a 不是根元素) */
14.3.4. :last-child 伪类
:last-child 伪类 表示元素在其包含型兄弟节点中为最后一个。 等同于 :nth-last-child(1)。
14.3.5. :only-child 伪类
:only-child 伪类 表示没有兄弟节点的元素。 等同于 :first-child:last-child 或 :nth-child(1):nth-last-child(1), 但特异性更低。
14.4. 类型化子元素索引伪类
本节中的伪类与子元素索引伪类类似, 但它们是根据元素在其兄弟列表中属于同一类型(标签名)的元素中的索引进行解析的。
14.4.1. :nth-of-type() 伪类
:nth-of-type(An+B) 伪类
表示与 :nth-child(|An+B| of S) 匹配的元素,
其中 S 是与当前元素类型选择器和命名空间前缀匹配的类型选择器。
例如,
当判断一个 HTML
img
元素是否匹配本伪类时,
此处 S 为 html|img(假设已声明了合适的 html
命名空间)。
img:nth-of-type(2n+1) { float: right; } img:nth-of-type(2n) { float: left; }
注意:如果元素类型已提前确定, 该伪类等同于带类型选择器的 :nth-child()。 即 img:nth-of-type(2) 等同于 *:nth-child(2 of img)。
14.4.2. :nth-last-of-type() 伪类
:nth-last-of-type(An+B) 伪类
表示与 :nth-last-child(|An+B| of S) 匹配的元素,
其中 S 是与当前元素类型选择器和命名空间前缀匹配的类型选择器。
例如,
当判断一个 HTML
img
元素是否匹配本伪类时,
此处 S 为 html|img(假设已声明了合适的 html
命名空间)。
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)
14.4.3. :first-of-type 伪类
:first-of-type 伪类 表示与 :nth-of-type(1) 匹配的元素。
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>
14.4.4. :last-of-type 伪类
:last-of-type 伪类 表示与 :nth-last-of-type(1) 匹配的元素。
14.4.5. :only-of-type 伪类
:only-of-type 伪类 表示与 :first-of-type:last-of-type 匹配的元素。
15. 组合器
15.1. 后代组合器 (
)
有时,作者希望选择器描述某个元素是另一个元素在文档树中的后代(例如,“一个 em 元素被包含在 H1 元素内”)。 后代组合器用于表达这种关系。
后代组合器是将两个复合选择器用空白分隔开。
形如 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]
15.2. 子元素组合器 (>
)
子元素组合器 描述两个元素之间的父子关系。子元素组合器由 “大于号”(U+003E,>)字符构成, 用于分隔两个复合选择器。
body
的子元素:
body > p
下面的例子结合了后代组合器和子元素组合器。
div ol>li p
它表示一个 p 元素,是一个 li 元素的后代;该 li 元素必须是
一个 ol 元素的子元素;ol 元素必须
是 div
的后代。注意,这里省略了 “>” 组合器两侧的可选空白。
关于如何选中某个元素的第一个子元素, 请参见上文关于 :first-child 伪类的相关章节。
15.3.
紧邻兄弟组合器 (+
)
紧邻兄弟组合器由“加号” (U+002B,+)字符构成,用于分隔两个复合选择器。 由这两个 复合选择器表示的元素在文档树中拥有相同的父元素, 并且第一个 复合选择器表示的元素紧跟在第二个元素之前。 在判断元素是否相邻时,非元素节点(例如元素间的文本)会被忽略。
math + p
下列选择器在概念上与上例类似,只是添加了一个属性选择器 —— 它
为 h1 元素增加了约束,要求其拥有 class="opener"
:
h1.opener + h2
15.4.
后续兄弟组合器 (~
)
后续兄弟组合器由“波浪号” (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>
16. 网格结构选择器
二维网格中单元格与其所在行和列的双重关联, 无法通过分层标记语言中的父子关系来表示。 只能有一种关联通过层级结构表示; 另一种关联必须在文档语言语义中显式或隐式定义。在 HTML 和 DocBook 这两种最常见的分层标记语言中, 标记是以行为主(即行的关联通过层级结构表示); 列的关联必须被推断。 为了能够表示这种列关联关系,定义了列组合器、:nth-col() 和 :nth-last-col() 伪类。 在以列为主的格式中,这些伪类则用于匹配行的关联关系。
16.1. 列组合器 (||
)
列组合器 由两个管道符号组成(||), 表示某列元素与属于该列的单元格元素之间的关系。 列的归属仅根据文档语言的语义确定: 与元素如何展示无关。 如果一个单元格属于多个列, 可以用选择器表示其属于任意这些列。
col.selected || td { background: gray; color: white; font-weight: bold; }
<table> <col span="2"> <col class="selected"> <tr><td>A <td>B <td>C <tr><td colspan="2">D <td>E <tr><td>F <td colspan="2">G </table>
16.2. :nth-col() 伪类
:nth-col(An+B) 伪类表示属于某一列的单元格元素,
该列在其前面有 An+B-1 个列(对于任何正整数或零的 n
)。
列归属仅根据文档语言的语义确定:
与元素如何展示无关。
如果一个单元格属于多个列,
可以用选择器表示其属于任意这些列。
CSS Syntax 模块[CSS3SYN]定义了An+B 语法。
16.3. :nth-last-col() 伪类
:nth-last-col(An+B) 伪类表示属于某一列的单元格元素,
该列在其后面有 An+B-1 个列(对于任何正整数或零的 n
)。
列归属仅根据文档语言的语义确定:
与元素如何展示无关。
如果一个单元格属于多个列,
可以用选择器表示其属于任意这些列。
CSS Syntax 模块[CSS3SYN]定义了An+B 语法。
17. 选择器特异性的计算
某个元素的选择器特异性按如下方式计算:
- 统计选择器中的 ID 选择器数量 (= A)
- 统计选择器中的类选择器、属性选择器和伪类数量 (= B)
- 统计选择器中的类型选择器和伪元素数量 (= C)
- 忽略通用选择器
如果选择器是一个选择器列表, 则对列表中的每个选择器都要计算这个数值。 针对列表的匹配过程,实际生效的是列表中最具体的匹配选择器的特异性。
有些伪类为其他选择器提供“求值上下文”,因此它们的特异性有特殊定义:
- :is()、:not() 或 :has() 伪类的特异性 由其选择器列表 参数中最具体的复杂选择器的特异性替代。
- 类似地,:nth-child() 或 :nth-last-child() 选择器的特异性 是该伪类本身的特异性(作为一个伪类选择器计数一次), 加上其参数选择器列表中最具体的 复杂选择器的特异性(如果有)。
- :where() 伪类的特异性被替换为零。
- :is(em, #foo) 的特异性为 (1,0,0)——与 ID 选择器(#foo)一样——当与
<em>
、<p id=foo>
或<em id=foo>
匹配时。 - .qux:where(em, #foo#bar#baz) 的特异性为 (0,1,0): 只有 .qux(在 :where() 之外)贡献了特异性。
- :nth-child(even of li, .item) 的特异性为 (0,2,0)——相当于一个类选择器(.item)加一个伪类——当与
<li>
、<ul class=item>
或<li class=item id=foo>
匹配时。 - :not(em, strong#foo) 的特异性为 (1,0,1)——即标签选择器(strong)与 ID 选择器(#foo)结合——匹配任意元素时。
特异性比较时,依次比较三个组成部分: A 值较大的特异性更高; 如果 A 相等,则 B 值较大的更高; 如果 B 也相等,则 C 值较大的更高; 如果全部相等,则两者特异性相同。
由于存储限制, 实现可能会限制 A、B 或 C 的最大值。 如有限制,超过的值必须被限制到最大值,不能溢出。
* /* a=0 b=0 c=0 */ LI /* a=0 b=0 c=1 */ UL LI /* a=0 b=0 c=2 */ UL OL+LI /* a=0 b=0 c=3 */ H1 + *[REL=up] /* a=0 b=1 c=1 */ UL OL LI.red /* a=0 b=1 c=3 */ LI.red.level /* a=0 b=2 c=1 */ #x34y /* a=1 b=0 c=0 */ #s12:not(FOO) /* a=1 b=0 c=1 */ .foo :is(.bar, #baz) /* a=1 b=1 c=0 */
注意:同一个简单选择器可以重复出现,并且确实会提高特异性。
注意:HTML 中 style
属性指定样式的特异性,
请参见 CSS Style Attributes。[CSSSTYLEATTR]
18. 语法
选择器根据以下语法进行解析:
<selector-list> = <complex-selector-list> <complex-selector-list> = <complex-selector># <compound-selector-list> = <compound-selector># <simple-selector-list> = <simple-selector># <relative-selector-list> = <relative-selector># <complex-selector> = <compound-selector> [ <combinator>? <compound-selector> ]* <relative-selector> = <combinator>? <complex-selector> <compound-selector> = [ <type-selector>? <subclass-selector>* [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]! <simple-selector> = <type-selector> | <subclass-selector> <combinator> = '>' | '+' | '~' | [ '|' '|' ] <type-selector> = <wq-name> | <ns-prefix>? '*' <ns-prefix> = [ <ident-token> | '*' ]? '|' <wq-name> = <ns-prefix>? <ident-token> <subclass-selector> = <id-selector> | <class-selector> | <attribute-selector> | <pseudo-class-selector> <id-selector> = <hash-token> <class-selector> = '.' <ident-token> <attribute-selector> = '[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']' <attr-matcher> = [ '~' | '|' | '^' | '$' | '*' ]? '=' <attr-modifier> = i | s <pseudo-class-selector> = ':' <ident-token> | ':' <function-token> <any-value> ')' <pseudo-element-selector> = ':' <pseudo-class-selector>
在解释上述语法时,适用以下规则:
-
禁止出现空白符:
-
在<compound-selector>的顶层各组成部分之间(即在 <type-selector> 与 <subclass-selector>之间, 或在 <subclass-selector> 与 <pseudo-element-selector>之间,等等)。
-
在<type-selector>或<class-selector>的任何组成部分之间。
-
在<pseudo-element-selector>或<pseudo-class-selector>的冒号之间,或冒号与<ident-token>或<function-token>之间。
-
在<wq-name>的任何组成部分之间。
-
在<attr-matcher>的各组成部分之间。
-
在<combinator>的组成部分之间。
若两个<compound-selector>之间省略了<combinator>,则必须有空白符分隔。 (这表示使用了后代组合器。)
-
- 四个第2级伪元素(::before、::after、::first-line 和 ::first-letter) 为兼容旧版, 可以只用单个冒号开头、采用<pseudo-class-selector>语法表示。
- 在<id-selector>中,<hash-token>的值必须是标识符。
注意:选择器还受各种更具体的语法约束, 遵循上述语法是必要但不充分条件,要被视为有效选择器。 更多选择器解析规则见§ 3.9 无效选择器与错误处理。
注意:通常, <pseudo-element-selector>只在最后一个<compound-selector>的末尾才是有效的。 但某些情况下, 它后面可以跟更多的<pseudo-element-selector>或<pseudo-class-selector>; 这些情况需具体说明。 (例如,用户操作伪类允许在任何伪元素后使用, 树相关伪元素允许在::slotted()伪元素后使用。)
18.1. <forgiving-selector-list> 和 <forgiving-relative-selector-list>
由于兼容性原因, 选择器列表的一般行为是:如果列表中的任一选择器解析失败 (例如使用了新的或仅特定 UA 支持的选择器特性), 整个选择器列表都变为无效。 这会导致在使用新选择器同时兼容旧版用户代理时很难编写 CSS。
<forgiving-selector-list> 规则 会分别解析列表中的每个选择器, 并忽略解析失败的选择器, 这样剩余的选择器仍可使用。
注意:样式规则仍采用正常(严格)的选择器列表行为。<forgiving-selector-list> 用于一些函数, 如 :is(), 这些函数同样具有通用性。 虽然这对特异性有一些细微影响, 但将样式规则选择器包裹在 :is() 中,实际上“升级”为宽容解析。
在语法上,<forgiving-selector-list> 等价于
<any-value>?
。
然后会宽容选择器列表解析以获取实际值。
-
按语法解析逗号分隔列表, 从 input 得到 <complex-selector> 列表, 并将结果赋值给 selector list。
-
从 selector list 中移除所有解析失败项, 以及所有无效选择器项, 然后返回一个<selector-list>,表示 selector list 中剩余的项。 (可能为空。)
<forgiving-relative-selector-list> 与 <forgiving-selector-list> 完全一致, 不同之处在于它将组件解析为<relative-selector> 而不是 <complex-selector>。
19. API 钩子
为方便使用选择器相关概念编写规范, 本节定义了一些可被其他规范调用的 API 钩子。
随着对匹配和无效选择器定义更为严格,这些钩子是否还有必要?
名词比谓词更容易在规范间协调,
类似 querySelector
返回元素的顺序等细节貌似应该在 DOM 规范而非选择器规范中定义。
19.1. 解析选择器
本节定义如何从字符串 source解析选择器。 它返回一个复杂选择器列表, 或失败。
- 令 selector 为 按 CSS 语法解析 source 为 <selector-list> 的结果。 若返回失败, 说明是无效选择器; 返回失败。
- 若 selector 因其他原因是无效选择器 (例如包含未声明的命名空间前缀), 返回失败。
- 否则, 返回 selector。
19.2. 解析相对选择器
本节定义如何从字符串 source解析相对选择器。 它返回一个复杂选择器列表, 或失败。
- 令 selector 为 按 CSS 语法解析 source 为 <relative-selector-list> 的结果。 若返回失败, 说明是无效选择器; 返回失败。
- 若 selector 因其他原因是无效选择器 (例如包含未声明的命名空间前缀), 返回失败。
- 否则, 返回 selector。
19.3. 用选择器匹配元素
本节定义如何用选择器匹配元素。
使用此算法的 API 必须提供 selector 和 element。
调用者可选地提供:
该算法返回成功或失败。
对于给定 selector(视为复杂选择器列表)中的每个复杂选择器, 按下述方法将复杂选择器与 element 匹配。 若有任何复杂选择器匹配成功, 算法即返回成功;否则返回失败。
要用复杂选择器匹配元素, 需每次处理一个复合选择器,从右往左递归处理,定义如下:
- 若右侧复合选择器中的任一简单选择器 与该元素不匹配,则返回失败。
- 否则,若复杂选择器中仅有一个复合选择器,则返回成功。
- 否则,考虑所有可能与该元素通过最右侧组合器相关联的元素。 若去除最右侧复合选择器和组合器后,对这些元素中的任意一个进行选择器匹配操作返回成功,则返回成功。 否则,返回失败。
19.4. 用选择器匹配伪元素
本节定义如何用选择器匹配伪元素。
使用此算法的 API 必须提供 selector 和 pseudo-element。 也可以选提供与用选择器匹配元素算法一样的参数。
该算法返回成功或失败。
对于给定 selector 中的每个复杂选择器,若同时满足:
- 复杂选择器中最右侧简单选择器 能与 pseudo-element 匹配,并且
- 对该复杂选择器剩余部分(仅去除最右侧复杂选择器的最右侧简单选择器)、 pseudo-element 对应的元素以及所有可选参数运行 用复杂选择器匹配元素 算法返回成功,
否则 (即若上述条件对 selector 中所有复杂选择器都不成立), 返回失败。
19.5. 将选择器与树匹配
本节定义了如何将选择器与树匹配。
使用此算法的 API 必须提供一个选择器, 以及一个或多个根元素,用于指示选择器将搜索的子树。 所有根元素必须共享相同的根, 否则调用此算法无效。
它们还可以选择性地提供:
该算法返回一个(可能为空)元素列表。
- 从一组候选元素开始, 这些元素包括根元素及其所有后代元素, 按照包含 shadow 的树顺序排序, 除非另有说明。
- 如果提供了作用域根, 则从候选元素中移除所有不是至少一个作用域根的后代的元素。
- 初始化选择器匹配列表为空。
- 对于候选元素集合中的每个element:
附录 A:将源文档和数据映射到元素树的指导
本节为说明性内容。
DOM 描述的元素树结构非常强大且实用, 但其通用性足以建模几乎任何用于描述树状数据的语言 (甚至图结构,只需适当解释)。
某些语言,如 HTML,已经定义了从资源生成 DOM 对象的明确过程。 如果某种语言没有, 则必须定义这样的过程, 以便选择器能够应用于该语言的文档。
至少, 文档语言必须定义什么映射为 DOM 的“元素”概念。
节点之间的主要一对多关系——树结构中的父/子, 图结构中的元素/邻居——应该映射为元素的子节点。
元素的其他特征应映射为在 DOM 中具有类似作用的内容:
- type
-
如果文档语言中的元素有一些“类型”的概念,
用于区分不同元素组,
则应映射为“type”特性。
如果该“type”可拆分为“基础”名称和用于将名称分组为更高层级的“命名空间”, 后者应映射为“namespace”特性。 否则,元素不应有“namespace”特性, 整个名称应映射为“type”特性。
- id
-
如果元素的某个方面在整个文档中作为唯一标识符,
则应映射为“id”特性。
注意: 虽然 HTML 只允许元素有一个 ID, 但这不应被视为通用限制。 ID 的重要属性在于每个 ID 只能关联一个元素; 单个元素可以有效地拥有多个 ID。
- classes and attributes
- 元素中用于识别元素但通常在文档中不是唯一的方面, 应分别映射为“class”或“attribute”特性, 具体取决于它们是类似“标签”(仅字符串) 还是“属性”(名称/值对)
- pseudo-classes and pseudo-elements
-
如果有任何元素匹配任何伪类或拥有任何伪元素,
那必须明确定义。
有些伪类是*语法上的*, 如:has() 和:is(), 因此应始终有效。 需在某处指明。 可能结构性伪类只要子列表有序就总是有效。
- JSON 文档中的“元素” 是每个数组、对象、布尔、字符串、数字或 null。 数组和对象元素的内容为其子节点。
- 每个元素的类型为其 JS 类型名: “array”、“object”等。
- 对象的子元素 其键作为 class。
- 数组的子元素匹配:first-child、:nth-child()等伪类。
- 根对象匹配:root。
- 还定义了:val()和:contains() 伪类, 用于匹配具有特定值的布尔/数字/字符串元素 或包含特定子串的元素。
这种结构足以使用选择器对 JSON 文档进行强大且简洁的查询。
附录 B:为 Web 兼容性必须支持的废弃但必需的 -webkit-
解析怪癖
本附录为规范性内容。
由于 Web 兼容性方面的历史原因, 期望解析 Web 文档的用户代理必须支持以下功能:
-
所有其他名称以“-webkit-”字符串开头(ASCII 不区分大小写匹配), 且不是函数式表示法的伪元素 必须在解析时被视为有效。 (即,::-webkit-asdf 在解析时有效, 但 ::-webkit-jkl() 无效。) 如果它们未被识别和支持, 必须被视为不匹配任何内容,并被定义为未知 -webkit- 伪元素。
未知 -webkit- 伪元素必须以 ASCII 小写序列化。
这个怪癖是怎么回事?
选择器长期以来都有一种行为, 即单个未知/无效选择器 会使整个选择器列表失效 (而不是只使其所在的复杂选择器失效)。 工作组普遍认为这是历史遗留错误, 但目前无法修正, 因为太多样式表依赖这种行为, 不管是有意还是无意。
其中一个方面是, 在其他用户代理中使用供应商特定选择器 会使整个选择器无效, 从而整条样式规则都失效。 过去曾被有意利用——通过故意让规则在其他浏览器无效来隐藏样式, 也曾被无意利用, 比如有人为某元素设样式 同时也应用到供应商特定伪元素 (如某些浏览器提供的相关伪元素), 却没意识到这样会让整个规则在其他浏览器消失。
除上述更一般原因外, 基于 WebKit 的用户代理, 如 Safari 或 Chrome, 还有额外的怪癖, 即任何
::-webkit-
前缀的选择器在解析时都被视为有效。 (这很可能是早期 CSS 功能的遗留怪癖, 该功能后来被弃用, 最初设想所有可能的伪元素在解析时都有效, 以便作者将来能自定义伪元素。)与其他遗留怪癖类似, 如[QUIRKS]中记录的, 这一特定的供应商怪癖已变得如此普遍, 以至于其他用户代理也因网站依赖它而出现问题, 无论是有意还是无意。 因此,由于该怪癖实际上必须才能正确渲染现代网页, 进行规范化并要求所有用户代理支持, 能确保当前和未来的网页在各类用户代理中更有可能被正确渲染。
不过像往常一样, 有意依赖这些怪癖的网页 将会受到 CSSWG 成员和所有正直的 Web 开发者的批评和鄙视。
20. 变更
20.1. 自 2022 年 5 月 7 日工作草案以来的变更
自 2022 年 5 月 7 日工作草案 以来的重要变更:
-
新增 :open 和 :closed 伪类。 (Issue 7319)
-
禁止 伪元素 在 :has() 中,除非伪元素的定义明确允许。 (Issue 7463)
-
禁止嵌套 :has()。 (Issue 7344)
-
定义了 ::lang("") 以及未标记语言的元素的匹配方式。 (Issue 6915)
-
完全理清了“有作用域”和“相对”选择器的概念。 (Issue 6399)
-
同时移除了“使选择器绝对化”,直接用锚定元素定义相对选择器的匹配。
-
-
撤销了 :nth-child() 的复合选择器限制。 (Issue 3760)
-
定义了 :-webkit-autofill 遗留选择器别名。 (Issue 7474)
20.2. 自 2018 年 11 月 21 日工作草案以来的变更
自 2018 年 11 月 21 日工作草案 以来的重要变更:
- 移除了选择器配置文件,将 :has() 标记为可选和风险项。 (Issue 3925)
- 新增 § 3.6.4 子伪元素,定义了 子伪元素及相关术语。
- 新增 :defined。 (Issue 2258)
- 新增 :modal。 (Issue 6965)
- 新增 :fullscreen 和 :picture-in-picture。 (Issue 3796)
- 新增 :seeking、:buffering 和 :stalled 媒体播放状态伪类。 (Issue 3821)
- 新增 :muted 和 :volume-locked 声音状态伪类。 (Issue 3821 和 Issue 3933)
- 新增 :autofill。 (Issue 5775)
- 新增 :user-valid。 (讨论)
- 定义了 :is()、:where()、:has()、:nth-child() 和 :nth-last-child() 在包含无效选择器时不会使自身失效。 (Issue 3264)
- 暂时限制 :nth-child() 和 :nth-last-child() 中的选择器为 复合选择器。 (Issue 3760)
- 通过引用 [INFRA] 明确了区分大小写的字符串匹配。
- 明确了 UA 提供的占位符文本仍会触发 :placeholder-shown。
- 重写了 :focus-visible 的定义,使其更清晰。
- 将语法部分的提醒说明切换为规范性文本,描述当 <compound-selector> 之间缺少 <combinator> 标记时,必须有空白。
20.3. 自 2018 年 2 月 2 日工作草案以来的变更
自 2018 年 2 月 2 日工作草案 以来的重要变更:
- 将零特异性选择器命名为 :where()。 (Issue 2143)
- 将 :matches() 重命名为 :is()。 (Issue 3258)
- 重新定义了 :empty,使其忽略仅包含空白的节点。 (Issue 1967)
- 重新定义了 :blank,表示空的用户输入,而不是空元素。 (Issue 1283)
- 更改了 :is()、:has() 和 :nth-child() 的特异性,不再依赖于哪个选择器参数匹配。 (Issue 1027)
- 移除了 :drop() 伪类,因为 HTML 已移除相关功能。 (Issue 2257)
- 在属性选择器中新增了区分大小写标志
s
。 (Issue 2101) - 进一步说明了 :focus-visible。
- 新增 附录 B:为 Web 兼容性必须支持的废弃但必需的 -webkit- 解析怪癖,定义了 ::-webkit- 伪元素解析怪癖。 (Issue 3051)
- 重写了关于语法规则中允许空白的位置的说明,使其更清晰。 (见 § 18 语法。)
20.4. 自 2013 年 5 月 2 日工作草案以来的变更
自 2013 年 5 月 2 日工作草案 以来的重要变更包括:
- 新增 :target-within、:focus-within、:focus-visible、:playing 和 :paused 伪类。
- 新增零特异性的 :matches() 类型伪类,名称待定。
- 用 :has() 替换了主语指示符 (!) 功能。
- 将 :nth-match() 和 :nth-last-match() 选择器 替换为 :nth-child(… of selector) 和 :nth-last-child(… of selector)。
- 用 :drop() 替换了 :active-drop-target、:valid-drop-target、 :invalid-drop-target。
- 草拟了用于讨论的仅空或仅空白选择器 (见 开放议题。)
- 将 :user-error 重命名为 :user-invalid。 (见 讨论)
- 将 :nth-column()/:nth-last-column() 重命名为 :nth-col()/:nth-last-col(),以避免与 ::column 伪类混淆。
- 将 :local-link 伪类的非功能形式更改为支持片段 URL。
- 因兴趣不足,移除了
:local-link()
伪类的函数形式和引用组合器。 - 用 CSS 值定义语法重写了选择器语法。
- 将 相对选择器 从 有作用域选择器 中拆分出来,作为可独立调用的不同概念。
- 移动了 <An+B> 微语法的定义到 CSS 语法规范中。
-
新增章节:
- § 3.2 数据模型
-
§ 19 API 钩子
- 注意早期版本本节定义了 评估选择器 相关内容, 但该节现已移除。 引用该节的规范应改为引用 将选择器与树匹配的算法。
- 移除了 :matches() 和 :not() 内部组合器的限制; 见 讨论。
- 定义了 特异性对于 选择器列表 的计算方式。(原因?)
- 要求 :lang() 值中有星号时必须加引号; 只有碰巧为 CSS 标识符的语言代码可不加引号。
注意:2018 年 2 月 1 日的草案误提交了未完成的内容; 2 月 2 日已恢复此提交(顺便修复了部分链接)。
20.5. 自 2012 年 8 月 23 日工作草案以来的变更
自 2012 年 8 月 23 日工作草案 以来的重要变更包括:
- 新增 :placeholder-shown 伪类。
- 放宽了 :matches() 和 :not() 的部分限制。
- 定义了快速和完整的选择器配置文件(现称为“实时”和“快照”)。
- 改进了 特异性 的定义,以更好地处理 :matches()。
- 更新了语法。
- 完善了 <An+B> 表示法的定义。
- 新增了 作用域相对选择器的定义,将作用域约束改为作用域过滤,以减少与作用域包含的混淆。
- :local-link() 伪类现在会忽略末尾的斜杠。
20.6. 自 2011 年 9 月 29 日工作草案以来的变更
自 2011 年 9 月 29 日工作草案 以来的重要变更包括:
- 根据 RFC 4647 添加了语言变体处理。
- 新增了有作用域选择器。
- 新增了 :user-error(现称为 :user-invalid)。
- 新增了 :valid-drop-target。
- 将 列组合器 从双斜杠改为双管道。
20.7. 自 Level 3 以来的变更
自 Level 3 以来的新增内容:
- 扩展了 :not(),使其可接受选择器列表。
- 新增了 :is()、:where() 和 :has()。
- 新增了 :scope。
- 新增了 :any-link 和 :local-link。
- 新增了 时间维度伪类。
- 新增了 :target-within、:focus-within 和 :focus-visible。
- 新增了 :dir()。
- 扩展了 :lang() ,使其接受通配符匹配和语言码列表。
- 扩展了 :nth-child(),使其可接受选择器列表。
- 合并了来自 CSS 基本用户界面模块 Level 3 的输入选择器,并重新添加了 :indeterminate。
- 新增了 :blank 和 :user-invalid。
- 新增了 网格结构(列)选择器。
- 新增了区分大小写 / 不区分大小写属性值匹配标记。
21. 致谢
CSS 工作组感谢多年来为前代选择器规范做出贡献的所有人, 因为这些规范为本规范奠定了基础。 特别感谢以下人员对选择器 Level 4 的具体贡献: L. David Baron、 Andrew Fedoniouk、 Daniel Glazman、 Ian Hickson、 Grey Hodge、 Lachlan Hunt、 Anne van Kesteren、 Jason Cranford Teague、 Lea Verou
22. 隐私与安全注意事项
本规范引入了以下隐私与安全注意事项: