1. 引言
本节不具规范性。
测试
本节不具规范性,因此不需要测试。
选择器是一个布尔谓词, 接收树结构中的一个元素, 判断该元素是否匹配该选择器。
这些表达式可用于多种场景:
- 可直接在元素上,判断其是否符合某些条件,
例如 [DOM] 中定义的
element.matches()函数 - 应用于整个元素树来过滤,形成满足条件的元素集合,
例如 [DOM] 中的
document.querySelectorAll()函数或 CSS 样式规则的选择器。 - “反向使用”,用于生成能被特定选择器匹配的标记, 如 HAML 或 Emmet。
Selectors Level 1, 2 和 3 分别对应于CSS1、CSS2.1 和 Selectors Level 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 元素为锚点元素时匹配 | § 4.5 关系伪类: :has() | 4 |
E.warning
| 属于类 warning 的 E 元素(文档语言定义 class 的判定方式)。
| § 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 属性值与 bar 各种(ASCII 范围)大小写组合等价的 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:target
| 作为当前 URL 目标的 E 元素 | § 8.3 目标伪类: :target | 3 |
E:scope
| 作为作用域根的 E 元素 | § 8.4 参考元素伪类: :scope | 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 | § 12.1.1 :enabled 和 :disabled 伪类 | 3 |
E:read-writeE:read-only
| 可被用户更改或不可更改的用户界面元素 E | § 12.1.2 可变性伪类: :read-only 和 :read-write | 3-UI/4 |
E:placeholder-shown
| 当前显示占位符文本的输入控件 | § 12.1.3 占位符显示伪类: :placeholder-shown | 3-UI/4 |
E:default
| 在同组相关选项中为默认项的用户界面元素 E | § 12.1.5 默认选项伪类: :default | 3-UI/4 |
E:checkedE:uncheckedE:indeterminate
| 被选中(如单选框、复选框)、未选中或处于未定状态(既非选中也非未选中)的用户界面元素 E | § 12.2 输入值状态 | 3 |
E:validE:invalid
| 输入内容满足或不满足数据有效性语义的用户输入元素 E | § 12.3.1 有效性伪类: :valid 和 :invalid | 3-UI/4 |
E:in-rangeE:out-of-range
| 值在有效范围内/外的用户输入元素 E | § 12.3.2 范围伪类: :in-range 和 :out-of-range | 3-UI/4 |
E:requiredE:optional
| 要求输入/不要求输入的用户输入元素 E | § 12.3.3 可选性伪类: :required 和 :optional | 3-UI/4 |
E:user-invalid
| 一个由用户更改且用户输入的元素 E,其输入不正确(无效、超出范围、被要求但遗漏) | § 12.3.4 用户交互伪类: :user-valid 和 :user-invalid | 4 |
E:root
| 文档根元素 E | § 13.1 :root 伪类 | 3 |
E:empty
| 没有子节点(元素或文本,仅允许空白)的 E 元素 | § 13.2 :empty 伪类 | 3 |
E:nth-child(n [of S]?)
| E 是其父节点匹配 S 的第 n 个子元素 | § 13.3.1 :nth-child() 伪类 | 3/4 |
E:nth-last-child(n [of S]?)
| E 是其父节点匹配 S 的倒数第 n 个子元素 | § 13.3.2 :nth-last-child() 伪类 | 3/4 |
E:first-child
| 父节点的第一个子元素 E | § 13.3.3 :first-child 伪类 | 2 |
E:last-child
| 父节点的最后一个子元素 E | § 13.3.4 :last-child 伪类 | 3 |
E:only-child
| 父节点唯一的子元素 E | § 13.3.5 :only-child 伪类 | 3 |
E:nth-of-type(n)
| E 是其类型的第 n 个兄弟元素 | § 13.4.1 :nth-of-type() 伪类 | 3 |
E:nth-last-of-type(n)
| E 是其类型的倒数第 n 个兄弟元素 | § 13.4.2 :nth-last-of-type() 伪类 | 3 |
E:first-of-type
| E 是其类型的第一个兄弟元素 | § 13.4.3 :first-of-type 伪类 | 3 |
E:last-of-type
| E 是其类型的最后一个兄弟元素 | § 13.4.4 :last-of-type 伪类 | 3 |
E:only-of-type
| E 是其类型的唯一兄弟元素 | § 13.4.5 :only-of-type 伪类 | 3 |
E F
| E 元素的 F 类型后代元素 | § 14.1 后代组合符 ( ) | 1 |
E > F
| E 元素的 F 类型子元素 | § 14.2 子代组合符 (>) | 2 |
E + F
| 紧跟在 E 元素之后的 F 元素 | § 14.3 相邻兄弟组合符 (+) | 2 |
E ~ F
| 被 E 元素前置的 F 元素 | § 14.4 通用兄弟组合符 (~) | 3 |
注意:一些 4 级选择器(上表标记为“3-UI”)首次出现在[CSS3UI]。
测试
- css3-modsel-1.xml (可视化测试) (source)
- css3-modsel-10.xml (可视化测试) (source)
- css3-modsel-100.xml (可视化测试) (source)
- css3-modsel-100b.xml (可视化测试) (source)
- css3-modsel-101.xml (live test) (source)
- css3-modsel-101b.xml (live test) (source)
- css3-modsel-102.xml (live test) (source)
- css3-modsel-102b.xml (可视化测试) (source)
- css3-modsel-103.xml (live test) (source)
- css3-modsel-103b.xml (live test) (source)
- css3-modsel-104.xml (可视化测试) (source)
- css3-modsel-104b.xml (可视化测试) (source)
- css3-modsel-105.xml (live test) (source)
- css3-modsel-105b.xml (live test) (source)
- css3-modsel-106.xml (live test) (source)
- css3-modsel-106b.xml (live test) (source)
- css3-modsel-107.xml (可视化测试) (source)
- css3-modsel-107b.xml (可视化测试) (source)
- css3-modsel-108.xml (live test) (source)
- css3-modsel-108b.xml (live test) (source)
- css3-modsel-109.xml (live test) (source)
- css3-modsel-109b.xml (live test) (source)
- css3-modsel-11.xml (可视化测试) (source)
- css3-modsel-110.xml (live test) (source)
- css3-modsel-110b.xml (live test) (source)
- css3-modsel-111.xml (可视化测试) (source)
- css3-modsel-111b.xml (可视化测试) (source)
- css3-modsel-112.xml (live test) (source)
- css3-modsel-112b.xml (live test) (source)
- css3-modsel-113.xml (可视化测试) (source)
- css3-modsel-113b.xml (可视化测试) (source)
- css3-modsel-114.xml (可视化测试) (source)
- css3-modsel-114b.xml (可视化测试) (source)
- css3-modsel-115.xml (live test) (source)
- css3-modsel-115b.xml (live test) (source)
- css3-modsel-116.xml (live test) (source)
- css3-modsel-116b.xml (live test) (source)
- css3-modsel-117.xml (live test) (source)
- css3-modsel-117b.xml (live test) (source)
- css3-modsel-118.xml (可视化测试) (source)
- css3-modsel-119.xml (可视化测试) (source)
- css3-modsel-120.xml (可视化测试) (source)
- css3-modsel-121.xml (可视化测试) (source)
- css3-modsel-122.xml (live test) (source)
- css3-modsel-123.xml (可视化测试) (source)
- css3-modsel-123b.xml (可视化测试) (source)
- css3-modsel-124.xml (可视化测试) (source)
- css3-modsel-124b.xml (可视化测试) (source)
- css3-modsel-125.xml (live test) (source)
- css3-modsel-125b.xml (live test) (source)
- css3-modsel-126.xml (live test) (source)
- css3-modsel-126b.xml (live test) (source)
- css3-modsel-127.xml (live test) (source)
- css3-modsel-127b.xml (live test) (source)
- css3-modsel-128.xml (live test) (source)
- css3-modsel-128b.xml (live test) (source)
- css3-modsel-129.xml (live test) (source)
- css3-modsel-129b.xml (live test) (source)
- css3-modsel-13.xml (可视化测试) (source)
- css3-modsel-130.xml (可视化测试) (source)
- css3-modsel-130b.xml (可视化测试) (source)
- css3-modsel-131.xml (可视化测试) (source)
- css3-modsel-131b.xml (可视化测试) (source)
- css3-modsel-132.xml (可视化测试) (source)
- css3-modsel-132b.xml (可视化测试) (source)
- css3-modsel-133.xml (可视化测试) (source)
- css3-modsel-133b.xml (可视化测试) (source)
- css3-modsel-134.xml (live test) (source)
- css3-modsel-134b.xml (live test) (source)
- css3-modsel-135.xml (live test) (source)
- css3-modsel-135b.xml (live test) (source)
- css3-modsel-136.xml (live test) (source)
- css3-modsel-136b.xml (live test) (source)
- css3-modsel-137.xml (可视化测试) (source)
- css3-modsel-137b.xml (可视化测试) (source)
- css3-modsel-138.xml (可视化测试) (source)
- css3-modsel-138b.xml (可视化测试) (source)
- css3-modsel-139.xml (可视化测试) (source)
- css3-modsel-139b.xml (可视化测试) (source)
- css3-modsel-14.xml (可视化测试) (source)
- css3-modsel-140.xml (可视化测试) (source)
- css3-modsel-140b.xml (可视化测试) (source)
- css3-modsel-141.xml (live test) (source)
- css3-modsel-141b.xml (live test) (source)
- css3-modsel-142.xml (live test) (source)
- css3-modsel-142b.xml (live test) (source)
- css3-modsel-143.xml (live test) (source)
- css3-modsel-143b.xml (live test) (source)
- css3-modsel-144.xml (可视化测试) (source)
- css3-modsel-145a.xml (可视化测试) (source)
- css3-modsel-145b.xml (可视化测试) (source)
- css3-modsel-146a.xml (可视化测试) (source)
- css3-modsel-146b.xml (可视化测试) (source)
- css3-modsel-147a.xml (可视化测试) (source)
- css3-modsel-147b.xml (可视化测试) (source)
- css3-modsel-148.xml (live test) (source)
- css3-modsel-149.xml (live test) (source)
- css3-modsel-149b.xml (live test) (source)
- css3-modsel-14b.xml (live test) (source)
- css3-modsel-14c.xml (可视化测试) (source)
- css3-modsel-14d.xml (可视化测试) (source)
- css3-modsel-14e.xml (可视化测试) (source)
- css3-modsel-15.xml (可视化测试) (source)
- css3-modsel-150.xml (可视化测试) (source)
- css3-modsel-151.xml (live test) (source)
- css3-modsel-152.xml (live test) (source)
- css3-modsel-153.xml (可视化测试) (source)
- css3-modsel-154.xml (live test) (source)
- css3-modsel-155.xml (live test) (source)
- css3-modsel-155a.xml (live test) (source)
- css3-modsel-155b.xml (live test) (source)
- css3-modsel-155c.xml (live test) (source)
- css3-modsel-155d.xml (live test) (source)
- css3-modsel-156.xml (live test) (source)
- css3-modsel-156b.xml (live test) (source)
- css3-modsel-156c.xml (live test) (source)
- css3-modsel-157.xml (live test) (source)
- css3-modsel-158.xml (live test) (source)
- css3-modsel-159.xml (manual test) (source)
- css3-modsel-15b.xml (live test) (source)
- css3-modsel-16.xml (manual test) (source)
- css3-modsel-160.xml (live test) (source)
- css3-modsel-161.xml (manual test) (source)
- css3-modsel-166.xml (可视化测试) (source)
- css3-modsel-166a.xml (可视化测试) (source)
- css3-modsel-167.xml (可视化测试) (source)
- css3-modsel-167a.xml (可视化测试) (source)
- css3-modsel-168.xml (live test) (source)
- css3-modsel-168a.xml (live test) (source)
- css3-modsel-169.xml (live test) (source)
- css3-modsel-169a.xml (live test) (source)
- css3-modsel-17.xml (manual test) (source)
- css3-modsel-170.xml (live test) (source)
- css3-modsel-170a.xml (live test) (source)
- css3-modsel-170b.xml (live test) (source)
- css3-modsel-170c.xml (live test) (source)
- css3-modsel-170d.xml (live test) (source)
- css3-modsel-171.xml (可视化测试) (source)
- css3-modsel-172a.xml (live test) (source)
- css3-modsel-172b.xml (live test) (source)
- css3-modsel-173a.xml (live test) (source)
- css3-modsel-173b.xml (live test) (source)
- css3-modsel-174a.xml (可视化测试) (source)
- css3-modsel-174b.xml (可视化测试) (source)
- css3-modsel-175a.xml (live test) (source)
- css3-modsel-175b.xml (live test) (source)
- css3-modsel-175c.xml (live test) (source)
- css3-modsel-176.xml (live test) (source)
- css3-modsel-177a.xml (manual test) (source)
- css3-modsel-177b.xml (live test) (source)
- css3-modsel-178.xml (live test) (source)
- css3-modsel-179.xml (live test) (source)
- css3-modsel-179a.xml (可视化测试) (source)
- css3-modsel-18.xml (manual test) (source)
- css3-modsel-180a.xml (可视化测试) (source)
- css3-modsel-181.xml (可视化测试) (source)
- css3-modsel-182.xml (可视化测试) (source)
- css3-modsel-183.xml (可视化测试) (source)
- css3-modsel-184a.xml (live test) (source)
- css3-modsel-184b.xml (live test) (source)
- css3-modsel-184c.xml (live test) (source)
- css3-modsel-184d.xml (live test) (source)
- css3-modsel-184e.xml (live test) (source)
- css3-modsel-184f.xml (live test) (source)
- css3-modsel-18a.xml (manual test) (source)
- css3-modsel-18b.xml (manual test) (source)
- css3-modsel-18c.xml (manual test) (source)
- css3-modsel-19.xml (manual test) (source)
- css3-modsel-19b.xml (manual test) (source)
- css3-modsel-2.xml (可视化测试) (source)
- css3-modsel-20.xml (manual test) (source)
- css3-modsel-21.xml (manual test) (source)
- css3-modsel-21b.xml (可视化测试) (source)
- css3-modsel-21c.xml (可视化测试) (source)
- css3-modsel-22.xml (可视化测试) (source)
- css3-modsel-25.xml (可视化测试) (source)
- css3-modsel-27.xml (可视化测试) (source)
- css3-modsel-27a.xml (可视化测试) (source)
- css3-modsel-27b.xml (可视化测试) (source)
- css3-modsel-28.xml (可视化测试) (source)
- css3-modsel-28b.xml (可视化测试) (source)
- css3-modsel-29.xml (可视化测试) (source)
- css3-modsel-29b.xml (可视化测试) (source)
- css3-modsel-3.xml (可视化测试) (source)
- css3-modsel-30.xml (可视化测试) (source)
- css3-modsel-31.xml (可视化测试) (source)
- css3-modsel-32.xml (可视化测试) (source)
- css3-modsel-33.xml (可视化测试) (source)
- css3-modsel-34.xml (可视化测试) (source)
- css3-modsel-35.xml (可视化测试) (source)
- css3-modsel-36.xml (可视化测试) (source)
- css3-modsel-37.xml (可视化测试) (source)
- css3-modsel-38.xml (可视化测试) (source)
- css3-modsel-39.xml (可视化测试) (source)
- css3-modsel-39a.xml (可视化测试) (source)
- css3-modsel-39b.xml (可视化测试) (source)
- css3-modsel-39c.xml (可视化测试) (source)
- css3-modsel-3a.xml (可视化测试) (source)
- css3-modsel-4.xml (可视化测试) (source)
- css3-modsel-41.xml (可视化测试) (source)
- css3-modsel-41a.xml (可视化测试) (source)
- css3-modsel-42.xml (可视化测试) (source)
- css3-modsel-42a.xml (可视化测试) (source)
- css3-modsel-43.xml (可视化测试) (source)
- css3-modsel-43b.xml (可视化测试) (source)
- css3-modsel-44.xml (可视化测试) (source)
- css3-modsel-44b.xml (可视化测试) (source)
- css3-modsel-44c.xml (可视化测试) (source)
- css3-modsel-44d.xml (可视化测试) (source)
- css3-modsel-45.xml (可视化测试) (source)
- css3-modsel-45b.xml (可视化测试) (source)
- css3-modsel-45c.xml (可视化测试) (source)
- css3-modsel-46.xml (可视化测试) (source)
- css3-modsel-46b.xml (可视化测试) (source)
- css3-modsel-47.xml (可视化测试) (source)
- css3-modsel-48.xml (live test) (source)
- css3-modsel-49.xml (live test) (source)
- css3-modsel-5.xml (可视化测试) (source)
- css3-modsel-50.xml (可视化测试) (source)
- css3-modsel-51.xml (可视化测试) (source)
- css3-modsel-52.xml (可视化测试) (source)
- css3-modsel-53.xml (可视化测试) (source)
- css3-modsel-54.xml (live test) (source)
- css3-modsel-55.xml (live test) (source)
- css3-modsel-56.xml (live test) (source)
- css3-modsel-57.xml (可视化测试) (source)
- css3-modsel-57b.xml (可视化测试) (source)
- css3-modsel-59.xml (live test) (source)
- css3-modsel-6.xml (可视化测试) (source)
- css3-modsel-60.xml (live test) (source)
- css3-modsel-61.xml (manual test) (source)
- css3-modsel-62.xml (manual test) (source)
- css3-modsel-63.xml (manual test) (source)
- css3-modsel-64.xml (manual test) (source)
- css3-modsel-65.xml (manual test) (source)
- css3-modsel-66.xml (manual test) (source)
- css3-modsel-66b.xml (可视化测试) (source)
- css3-modsel-67.xml (可视化测试) (source)
- css3-modsel-7.xml (可视化测试) (source)
- css3-modsel-70.xml (可视化测试) (source)
- css3-modsel-72.xml (可视化测试) (source)
- css3-modsel-72b.xml (可视化测试) (source)
- css3-modsel-73.xml (可视化测试) (source)
- css3-modsel-73b.xml (可视化测试) (source)
- css3-modsel-74.xml (可视化测试) (source)
- css3-modsel-74b.xml (可视化测试) (source)
- css3-modsel-75.xml (可视化测试) (source)
- css3-modsel-75b.xml (可视化测试) (source)
- css3-modsel-76.xml (可视化测试) (source)
- css3-modsel-76b.xml (可视化测试) (source)
- css3-modsel-77.xml (可视化测试) (source)
- css3-modsel-77b.xml (可视化测试) (source)
- css3-modsel-78.xml (可视化测试) (source)
- css3-modsel-78b.xml (可视化测试) (source)
- css3-modsel-79.xml (可视化测试) (source)
- css3-modsel-7b.xml (live test) (source)
- css3-modsel-8.xml (可视化测试) (source)
- css3-modsel-80.xml (可视化测试) (source)
- css3-modsel-81.xml (可视化测试) (source)
- css3-modsel-81b.xml (可视化测试) (source)
- css3-modsel-82.xml (可视化测试) (source)
- css3-modsel-82b.xml (可视化测试) (source)
- css3-modsel-83.xml (live test) (source)
- css3-modsel-86.xml (可视化测试) (source)
- css3-modsel-87.xml (live test) (source)
- css3-modsel-87b.xml (live test) (source)
- css3-modsel-88.xml (可视化测试) (source)
- css3-modsel-88b.xml (可视化测试) (source)
- css3-modsel-89.xml (可视化测试) (source)
- css3-modsel-9.xml (可视化测试) (source)
- css3-modsel-90.xml (live test) (source)
- css3-modsel-90b.xml (live test) (source)
- css3-modsel-91.xml (可视化测试) (source)
- css3-modsel-92.xml (可视化测试) (source)
- css3-modsel-93.xml (可视化测试) (source)
- css3-modsel-94.xml (可视化测试) (source)
- css3-modsel-94b.xml (可视化测试) (source)
- css3-modsel-95.xml (可视化测试) (source)
- css3-modsel-96.xml (可视化测试) (source)
- css3-modsel-96b.xml (可视化测试) (source)
- css3-modsel-97.xml (可视化测试) (source)
- css3-modsel-97b.xml (可视化测试) (source)
- css3-modsel-98.xml (可视化测试) (source)
- css3-modsel-98b.xml (可视化测试) (source)
- css3-modsel-99.xml (live test) (source)
- css3-modsel-99b.xml (live test) (source)
- css3-modsel-d1.xml (可视化测试) (source)
- css3-modsel-d1b.xml (可视化测试) (source)
- css3-modsel-d2.xml (可视化测试) (source)
- css3-modsel-d3.xml (可视化测试) (source)
- css3-modsel-d4.xml (可视化测试) (source)
Tests that do not relate to any section
- eof-right-after-selector-crash.html (live test) (source)
- eof-some-after-selector-crash.html (live test) (source)
- hash-collision.html (live test) (source)
- invalid-pseudos.html (live test) (source)
- selector-after-font-family.html (live test) (source)
3. 选择器语法与结构
3.1. 结构和术语
选择器表示树结构中元素的特定模式。 选择器可以指代简单选择器、复合选择器、复杂选择器,或选择器列表。 选择器的主体是 选择器所定义的任何元素; 即任何匹配该选择器的元素。
简单选择器是对元素的单一条件。 类型选择器、通用选择器、 属性选择器、 类选择器、ID 选择器, 或伪类均为简单选择器。 (它在选择器<simple-selector>语法中表示。) 某个元素被认为匹配 一个简单选择器, 当该简单选择器,如本规范所定义,并符合 文档语言时,能准确描述该元素。
复合选择器是 一组未由组合符分隔的简单选择器序列, 表示对单一元素的同时成立的多个条件。 若包含类型选择器 或通用选择器, 该选择器必须位于序列首位。 序列中只允许有一个类型选择器或通用选择器。 (复合选择器在选择器 <compound-selector>语法中表示。) 某个元素被认为匹配 一个复合选择器, 当它同时匹配该复合选择器中的所有简单选择器。
注意:由于空格代表后代组合符, 所以复合选择器内的简单选择器之间不能有空格。
伪复合选择器 是伪元素选择器, 可后跟多个伪类选择器, 可前接复合选择器或另一个 伪复合选择器, 且两者之间不能有组合符。 (伪复合选择器在选择器 <pseudo-compound-selector>语法中表示。) 一个伪元素 当其名称、所匹配的额外伪类条件均符合,且拥有前置选择器所代表的 源元素时, 被认为匹配一个伪复合选择器。 如果没有前置选择器,则假定使用通用选择器。 (例如,.foo ::before等价于.foo *::before, 与.foo::before不同。)
注意: 伪复合选择器 不是 复合选择器, 不能用于仅允许复合选择器的位置。 伪复合选择器表现为其自带了一个 组合符, 用来表达与源元素的关系, 就像>组合符 表达父子关系一样。
组合符表示两侧复合选择器之间两个元素的关系条件。
选择器4级的组合符包括:
后代组合符(空格),
子代组合符
(U+003E,>),
相邻兄弟组合符(U+002B,+),
以及通用兄弟组合符(U+007E,~)。
如果两个元素间关系满足组合符的条件,则认为其匹配该
组合符。
复杂选择器 是由一个或多个复合选择器 和/或伪复合选择器组成的序列, 复合选择器之间以 组合符分隔。 它表示对具有特定组合符关系的一组元素的同步条件。 (复杂选择器在<complex-selector>语法中表示。) 某个元素或伪元素 同时满足序列最后一个复合或伪复合选择器 并且每个前序单元均正确匹配某元素或伪元素, 且二者间的关系由其分隔的组合符所规范(伪复合选择器则为正确 源元素关系),则被认为匹配 复杂选择器。
.ancestor > .foo.bar匹配这些元素的子集: 仅父元素(由>组合符指示) 有 "ancestor" 类的那些元素。
简单/复合/复杂选择器列表是由逗号分隔的简单、 复合或复杂选择器的列表。 当类型不重要或上下文中已明确时,也可简称为选择器列表; 若类型未注明但重要,则默认指复杂选择器列表。 (有关选择器列表 及其形式语法的详细说明,参见§ 4.1 选择器列表和语法部分的 <*-selector-list> 规则。) 元素只要匹配该选择器列表中任何(至少一个)选择器, 就认为匹配该列表。
3.2. 数据模型
选择器是在元素树(如 DOM)上进行匹配的。[DOM] 在本规范中, 这可以称为“文档树”或“源文档”。
每个元素可能具有以下五种属性之一, 均可被选择器匹配, 并全部以字符串方式比较:
- 元素的类型(又称标签名)。
- 元素的命名空间。
- ID。
- 其所属的类(组名)。
- 属性,名-值对。
许多选择器依赖于文档语言(即文档树的语言和语义) 及/或宿主语言(即使用选择器语法的语言)的语义。 例如,:lang()选择器依赖于文档语言(如 HTML), 决定元素如何与语言对应。 另一个例子,::first-line伪元素 则依赖于宿主语言(如 CSS), 以定义::first-line伪元素 的含义与作用范围。
3.2.1. 无特性的元素
测试
虽然某些元素可能缺少上述任何功能, 但有些元素是无特征的。 一个无特征元素不会 匹配任何选择器, 除非:
如果某个选择器本可匹配无特征元素, 但仅因存在默认命名空间[CSS-NAMESPACES-3](因为无特征元素 除非另有定义,否则没有命名空间), 默认命名空间不会阻止匹配。
像:not(.foo:host)这样的逻辑组合永远不会匹配host元素 (即使它没有 "foo" 类), 因为.foo:host中的所有简单选择器 并不都允许匹配 shadow host。
同样,:not(:host > .foo)也永远不会匹配shadow host, 即使shadow host确实*不是*自己的后代, 也没有 "foo" 类, 因为复杂选择器参数的主题 (.foo) 不允许匹配shadow host。
前文:has()的规则也类似。 即使shadow host包含.foo后代,:has(.foo) 也不会匹配它, 因为复合选择器的其他部分 (为空) 并不包含可以匹配host的简单选择器。 必须写成:host:has(.foo)才能匹配host元素。
3.3. 作用域选择器
某些宿主应用可选择限定选择器 到文档某个特定的子树或片段, 限定子树的根称为限定根。
当选择器被限定后, 仅当元素是限定根的后代时才会匹配。 (选择器的其余部分可不受限制; 只有最终被选中的元素必须在该作用域内。)
querySelector() 方法在[DOM]中定义,允许作者
相对于所调用的元素评估限定选择器。
调用如 widget
只会查找
a
元素,该元素必须在 widget 元素内部,
并会忽略文档中其他位置
的
a
元素。
3.4. 相对选择器
某些上下文可以接受相对选择器, 它是一种表示相对于一个或多个相对选择器锚点元素的选择器简写。 相对选择器以组合符开头, 并默认在选择器起始处隐含一个代表锚点元素的选择器。 (如果没有组合符, 则默认使用后代组合符。)
相对选择器在选择器<relative-selector>语法中表示, 相对选择器列表用<relative-selector-list>表示。
3.5. 伪类
伪类是简单选择器,它们允许根据 文档树之外的信息 或者用其他简单选择器难以或无法表达的情况进行选择。 伪类还可能是动态的, 即当用户与文档交互时,元素可以获得或失去伪类状态, 而无需更改文档本身。伪类不会出现在文档源码或文档树中,也不会修改它们。
伪类的语法 由 ":"(U+003A COLON) 后跟伪类名(作为CSS 标识符)组成, 如果属于函数型伪类, 则还要在其后加一对括号并包含其参数。
例如,:valid 是 普通伪类, :lang() 是 函数型伪类。
和所有CSS关键字一样,伪类的名称是ASCII 大小写不敏感的。 在伪类名和冒号之间,不允许有空白, 通常CSS语法中, 函数型伪类的函数名与其左括号之间也不允许有空白 (因此会组成一个CSS 函数 token)。 同样, 括号内的参数允许存在空白 (除非另有说明)。
像其他简单选择器一样,伪类可以出现在 选择器中包含的所有复合选择器里, 并且必须位于类型选择器或 通用选择器之后(如有)。
注意: 某些伪类是互斥的 (即含有这些伪类的复合选择器 虽然合法,但永远不会匹配任何元素), 也有些伪类可以同时应用到同一元素。
3.6. 伪元素
类似于某些伪类能够表示文档树中未直接存在的附加状态信息, 伪元素代表了文档树中未直接存在的元素。 它们用于构建关于文档树的抽象, 超越文档树本身所提供的界限。 例如, 伪元素可以用于选择文档中 不对应于任何文档语言元素的部分 (包括跨越元素边界或不适合其树结构的区域); 或用于表示文档树中不存在或在文档树的其他投影中的内容; 或依赖于样式、布局、用户交互等未反映在文档树中的过程所提供的信息。
伪元素也可以 代表完全不存在于源文档中的内容, 例如::before 和 ::after 伪元素, 它们允许在任何元素内容的前后插入额外内容。
和伪类一样,伪元素不会 出现在文档源码或文档树中,也不会修改它们。 因此,它们也不会影响结构型伪类 或与其源元素或其树相关的其他选择器的解释。
宿主语言定义了哪些伪元素存在、其类型及能力。 CSS中的伪元素定义见 [CSS21](第2级)、 [SELECT](第3级)、 和 [CSS-PSEUDO-4](第4级)。
3.6.1. 语法
伪元素的语法为“::”(两个U+003A冒号字符), 后跟该伪元素名称(必须是标识符), 若为函数型伪元素, 则需加上一对括号和其参数。伪元素名是 ASCII大小写不敏感的。 两个冒号之间以及冒号与名称之间不允许有空白。
由于CSS Level 1 和 CSS Level 2中,伪元素与伪类都采用了单冒号语法, 用户代理也必须接受第1级和第2级伪元素的旧单冒号写法 (即::before、::after、::first-line、和::first-letter)。 该兼容写法在其他伪元素中不允许。 但是,由于该语法已弃用, 作者应为这些伪元素使用第3级及以后的“::”双冒号语法。
3.6.2. 绑定文档树
伪元素不会独立于文档树存在: 它们总是绑定在页面上的另一个元素上, 即它们的源元素。 在语法上,伪元素紧跟其 复合选择器后出现,该复合选择器 代表其源元素。 如果此复合选择器省略, 则假定为通用选择器*。
选择器::first-line等同于*::first-line, 即在文档中每个元素上的::first-line伪元素。
当在选择器中遇到伪元素时, 其前半部分选择对应该伪元素的源元素; 之后(如有)选择器部分作用于伪元素本身。 (见下文。)
3.6.3. 伪元素的伪类化
某些伪元素可直接 追加特定伪类的任何组合, 在这种情况下,只有伪元素处于对应状态时 伪元素才会被表示。 本规范允许任意伪元素 追加任何组合的逻辑组合伪类以及用户操作伪类。 其他规范可允许还可以为特定伪类 追加到特定伪元素上。 未明确定义的组合为无效选择器。
注意:逻辑组合伪类会将关于位置选择器有效性的任何约束传递给其参数。
注意::first-line:hover和:hover::first-line差别很大, 后者匹配任何被悬停的源元素的首行! 例如,:hover::first-line也会匹配当段落第二行悬停时的首行, 而::first-line:hover仅当首行自身悬停时才会匹配。
3.6.4. 子伪元素
有些伪元素 能成为其他伪元素的源元素, 这些被定义为该子伪元素, 而当前元素则为源伪元素。 例如, 当::before被赋予list-item display类型时, 它就成了::before::marker 子伪元素的源伪元素。
当需要区分时, 最终源元素 指代产生伪元素的实际(非伪)元素。
除非相应的子伪元素在其它规范中明确定义, 在另一个伪元素选择器之后复合的伪元素选择器不是有效的。 例如,::before::before是无效的选择器, 但::before::marker是有效的 (如果实现支持::before::marker 子伪元素)。
3.6.5. 内部结构
某些伪元素 被定义为拥有内部结构。 这些伪元素可在其后使用子/后代组合符 用于表达这样的结构关系。 否则,在伪元素后出现组合符的选择器为无效。
注意: 未来的规范可能会扩展已有伪元素的能力, 因此某些当前无效的选择器(如::first-line :any-link) 在将来可能会变为有效。
此类伪元素的子节点也可以同时为其它元素的子节点。 但至少在CSS中,其渲染必须保证 盒子树 的树状特征得以保持。
3.7. 字符和大小写敏感性
测试
所有选择器语法都是ASCII 不区分大小写的(即[a-z]和[A-Z]等效), 除了那些 不受Selectors控制的部分: 特别是, 文档语言元素名、 属性名、 以及属性值 的大小写敏感性 取决于文档语言本身。
命名空间前缀的大小写敏感性定义见 [CSS3NAMESPACE]。 语言范围的大小写敏感性定义在:lang()小节。
Selectors里的空白 包括以下码点: SPACE (U+0020),TAB (U+0009),换行 (U+000A), 回车 (U+000D),以及换页 (U+000C)。 其它类似空格的码点,如EM SPACE (U+2003)和 全角空格 (U+3000),从不被视为语法空白。
选择器中的码位可以用反斜杠进行转义,
转义规则与 CSS 相同,详见转义规则。
[CSS21] 注意,对码位进行转义将会“抵消掉”
它在选择器中的任何特殊含义。
例如,选择器#foo>a包含了一个组合符,
而#foo\>a则会选择 id 为foo>a的元素。
3.8. 声明命名空间前缀
某些选择器支持命名空间前缀。 命名空间前缀的声明机制应由使用Selectors的语言进行规定。 如果该语言未指定如何声明命名空间前缀, 则视为没有声明前缀。 在CSS中,命名空间前缀使用@namespace规则声明。 [CSS3NAMESPACE]
3.9. 无效选择器与错误处理
测试
用户代理必须遵循以下处理无效选择器的规则:
- 选择器中出现解析错误, 例如出现未识别的标记或不允许在当前解析位置出现的标记 (见整体§ 16 语法以及各选择器的语法定义), 将导致该选择器无效。
- 包含未声明命名空间前缀的简单选择器无效
- 包含无效简单选择器、无效组合符 或无效标记的选择器无效。
- 包含无效选择器的选择器列表无效。
- 空选择器,即不包含任何复合选择器的选择器,无效。
注意: 遵循CSS的前向兼容解析原则, 用户代理必须将任何伪类、伪元素、组合符或其它 不支持的语法结构 视为无效。 参见部分实现。
无效选择器 表示且因此不会匹配任何内容。
3.10. 兼容别名
某些选择器存在兼容选择器别名。 这种别名在解析时会被转换为标准名称 (因此不会在任何代表选择器的对象模型中出现)。
4. 逻辑组合
测试
选择器逻辑可以通过复合(逻辑与)、选择器列表(逻辑或), 以及逻辑组合伪类 :is()、:where()和:not()进行操作。 逻辑组合伪类可出现在允许其它 伪类出现的任意位置, 但会将任何限制传递给其参数。 (例如,若只允许复合选择器, 那么:is()内只允许复合选择器。)
注意:由于在 :is()和:where()内,无效参数会被直接丢弃且不会让伪类 本身变为无效, 由上下文限制导致无效的选择器参数 也不会使:is()伪类本身无效。
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.html (live test) (source)
- is-default-ns-001.html (live test) (source)
- is-default-ns-002.html (live test) (source)
- is-default-ns-003.html (live test) (source)
- is-default-ns-002.html (live test) (source)
- is-default-ns-003.html (live test) (source)
- is-nested.html (live test) (source)
- is-specificity-shadow.html (live test) (source)
- is-specificity.html (live test) (source)
- is-where-basic.html (live test) (source)
- is-where-error-crash.html (live test) (source)
- is-where-error-recovery.html (live test) (source)
- is-where-not.html (live test) (source)
- is-where-pseudo-classes.html (live test) (source)
- is-where-pseudo-elements.html (live test) (source)
- is-where-shadow.html (live test) (source)
- is-where-visited.html (live test) (source)
- parse-is-where.html (live test) (source)
- parse-is.html (live test) (source)
- query-is.html (live test) (source)
匹配任意的伪类 :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)。
参见§ 15 选择器特异性计算。
伪元素不能通过匹配任意伪类表示; 它们在:is()内部无效。
默认命名空间声明不会影响 复合选择器,即任何单条选择器中的主题, 除非该复合选择器包含了 显式的通用选择器或 类型选择器。
*|*:is(:hover, :focus)
而下面这个选择器,仅表示默认命名空间下被悬停或聚焦的元素, 因为它在:is()内部用了显式的通用选择器:
*|*:is(*:hover, *:focus)
本规范早期草案中 曾用:matches()作为该伪类名称, 浏览器可视向后兼容需要实现此已废弃名作为 兼容选择器别名, 其行为同:is()。
4.3. 否定(匹配无任何项)伪类::not()
测试
- not-001.html (live test) (source)
- not-002.html (live test) (source)
- not-complex.html (live test) (source)
- not-default-ns-001.html (live test) (source)
- not-default-ns-002.html (live test) (source)
- not-default-ns-003.html (live test) (source)
- not-links.html (live test) (source)
- not-specificity.html (live test) (source)
- parse-not.html (live test) (source)
- query-where.html (live test) (source)
否定伪类 :not() 是一个函数型伪类,其参数为<complex-real-selector-list>。 它表示所有不被其参数选中的元素。
注意: 在Selectors Level 3中, 简单选择器只能有一个作为:not()的参数。
注意: :not()伪类的特异性 以其参数内选中者中特异性最高者为准; 即其行为与:not(:is(argument))完全一致。 参见§ 15 选择器特异性计算。
伪元素不能通过否定伪类表示; 它们在: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 {
/* 无效果 */
text-decoration: underline;
}
然而,通过使用:where(),作者可以明确表达自己的意图:
a:where(:not(:hover)) {
text-decoration: none;
}
nav a {
/* 现在生效! */
text-decoration: underline;
}
注意: Selectors的未来级别可能会引入额外参数, 用于显式设置该伪类实例的特异性。
4.5. 关系伪类::has()
测试
- has-argument-with-explicit-scope.html (live test) (source)
- has-basic.html (live test) (source)
- has-display-none-checked.html (live test) (source)
- has-focus-display-change.html (live test) (source)
- has-matches-to-uninserted-elements.html (live test) (source)
- has-nth-of-crash.html (live test) (source)
- has-relative-argument.html (live test) (source)
- has-sibling-chrome-crash.html (live test) (source)
- has-specificity.html (live test) (source)
- has-style-sharing-001.html (live test) (source)
- has-style-sharing-002.html (live test) (source)
- has-style-sharing-003.html (live test) (source)
- has-style-sharing-004.html (live test) (source)
- has-style-sharing-005.html (live test) (source)
- has-style-sharing-006.html (live test) (source)
- has-style-sharing-007.html (live test) (source)
- has-style-sharing-pseudo-001.html (live test) (source)
- has-style-sharing-pseudo-002.html (live test) (source)
- has-style-sharing-pseudo-003.html (live test) (source)
- has-style-sharing-pseudo-004.html (live test) (source)
- has-style-sharing-pseudo-005.html (live test) (source)
- has-style-sharing-pseudo-006.html (live test) (source)
- has-style-sharing-pseudo-007.html (live test) (source)
- has-style-sharing-pseudo-008.html (live test) (source)
- has-visited.html (live test) (source)
- attribute-or-elemental-selectors-in-has.html (live test) (source)
- child-indexed-pseudo-classes-in-has.html (live test) (source)
- has-pseudoclass-only-crash.html (live test) (source)
- defined-in-has.html (live test) (source)
- dir-pseudo-class-in-has.html (live test) (source)
- empty-pseudo-in-has.html (live test) (source)
- fullscreen-pseudo-class-in-has.html (live test) (source)
- has-append-first-node.html (live test) (source)
- has-complexity.html (live test) (source)
- has-css-nesting-shared.html (live test) (source)
- has-in-adjacent-position.html (live test) (source)
- has-in-ancestor-position.html (live test) (source)
- has-in-parent-position.html (live test) (source)
- has-in-sibling-position.html (live test) (source)
- has-invalidation-after-removing-non-first-element.html (live test) (source)
- has-invalidation-first-in-sibling-chain.html (live test) (source)
- has-invalidation-for-wiping-an-element.html (live test) (source)
- has-nested-pseudo-001-crash.html (live test) (source)
- has-nested-pseudo-002-crash.html (live test) (source)
- has-nested-pseudo-003-crash.html (live test) (source)
- has-pseudo-element.html (live test) (source)
- has-pseudoclass-only.html (live test) (source)
- has-sibling-insertion-removal.html (live test) (source)
- has-sibling.html (live test) (source)
- has-side-effect.html (live test) (source)
- has-unstyled.html (live test) (source)
- has-with-is-child-combinator.html (live test) (source)
- has-with-nesting-parent-containing-complex.html (live test) (source)
- has-with-nesting-parent-containing-hover.html (live test) (source)
- has-with-not.html (live test) (source)
- has-with-nth-child-sibling-remove.html (live test) (source)
- has-with-nth-child.html (live test) (source)
- has-with-pseudo-class.html (live test) (source)
- host-context-pseudo-class-in-has.html (live test) (source)
- host-has-shadow-tree-element-at-nonsubject-position.html (live test) (source)
- host-has-shadow-tree-element-at-subject-position.html (live test) (source)
- host-pseudo-class-in-has.html (live test) (source)
- input-pseudo-classes-in-has.html (live test) (source)
- is-pseudo-containing-complex-in-has.html (live test) (source)
- is-pseudo-containing-sibling-relationship-in-has.html (live test) (source)
- lang-pseudo-class-in-has-document-element.html (live test) (source)
- lang-pseudo-class-in-has-multiple-document-elements.html (live test) (source)
- lang-pseudo-class-in-has-xhtml.xhtml (live test) (source)
- lang-pseudo-class-in-has.html (live test) (source)
- link-pseudo-class-in-has.html (live test) (source)
- link-pseudo-in-has.html (live test) (source)
- location-pseudo-classes-in-has.html (live test) (source)
- media-loading-pseudo-classes-in-has.html (live test) (source)
- media-pseudo-classes-in-has.html (live test) (source)
- modal-pseudo-class-in-has.html (live test) (source)
- negated-has-in-nonsubject-position.html (live test) (source)
- not-pseudo-containing-complex-in-has.html (live test) (source)
- not-pseudo-containing-sibling-relationship-in-has.html (live test) (source)
- state-in-has.html (live test) (source)
- subject-has-invalidation-with-display-none-anchor-element.html (live test) (source)
- target-pseudo-in-has.html (live test) (source)
- typed-child-indexed-pseudo-classes-in-has.html (live test) (source)
- user-action-pseudo-classes-in-has.html (live test) (source)
- parse-has-disallow-nesting-has-inside-has.html (live test) (source)
- parse-has-forgiving-selector.html (live test) (source)
- parse-has.html (live test) (source)
关系型伪类:has() 是一个函数型伪类,其参数为<relative-selector-list>。 当以该元素作为相对选择器的锚点时,只要有任一相对选择器匹配到至少一个元素, 就表示该元素。
:has()伪类不可嵌套; :has()内部不能再有:has(),否则无效。 同样,除非被显式定义为:has-allowed 伪元素, 否则伪元素也不能作为:has()内的选择器。 (本规范未定义任何:has-allowed 伪元素, 但其他规范可能会定义。)
注意:伪元素一般不能用于:has(), 因为许多伪元素是否存在取决于其祖先的样式, 若允许:has()查询这些伪元素可能导致循环。
注意:由于:has()参数为<relative-selector-list>, 其参数本质上都是复杂选择器 (因为它们起始于(显式或隐式)组合符)。 这意味着,: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. 通用选择器
通用选择器 是一种特殊的类型选择器, 表示任意元素类型的元素。
通用选择器写作CSS限定名,本地名部分用星号(* U+002A)表示。
类似于类型选择器,
通用选择器也可加命名空间限定,
用于限定仅匹配属于该命名空间的元素,
并受§ 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 }
第一条规则(不计@namespaceat-rule 本身) 只匹配命名空间为"http://www.example.com"下的 h1元素。
第二条规则会匹配该命名空间内的所有元素。
第三条规则仅匹配没有命名空间的h1元素。
第四条规则会匹配任何命名空间(包括无命名空间)下的h1元素。
最后一条规则等价于第四条,因为未定义默认命名空间。
如果声明了默认命名空间,则复合选择器中未出现 类型选择器的,也仅匹配默认命名空间下的元素。
@namespace url("http://example.com/foo");
.special { ... }
.special选择器只会匹配"http://example.com/foo"命名空间内的元素, 即使选择器中未出现类型名(类型和命名空间在DOM中是成对出现的)。
带有未声明过的命名空间前缀的类型选择器或 通用选择器 属于无效选择器。
5.4. Defined伪类::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中a 元素上的hreflang属性), 详见 BCP 47 ([BCP47]) 或其后续规范。 针对lang或xml:lang进行语言子标签匹配, 可参考:lang() 伪类。
属性值必须是<ident-token>或<string-token>。[CSS3SYN]
如下属性选择器表示带有 title 属性的 h1 元素,
无论其属性值为何:
h1[title]
下例选择器表示其 class 属性值正好为 "example" 的 span 元素:
span[class="example"]
多属性选择器可同时表示一个元素的多个属性,或对同一属性的多重条件。比如,以下选择器表示 span 元素,
其 hello 属性值正好为 "Cleveland",
且 goodbye 属性值正好为 "Columbus":
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/"] { ... }
如下选择器表示 a 元素,
其 hreflang 属性正好为 "fr"。
a[hreflang=fr]
如下选择器表示 a 元素,
其 hreflang 属性值以 "en" 开头,
包括 "en"、"en-US"、"en-scouse":
a[hreflang|="en"]
如下选择器可表示 DIALOGUE 元素,
只要 character 属性的值取其一:
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/"]
下例选择器表示 href 属性值以 ".html" 结尾的 HTML a 元素:
a[href$=".html"]
下例选择器表示属性 title 值包含 "hello" 子串的 HTML 段落:
p[title*="hello"]
6.3. 大小写敏感性
测试
默认情况下,选择器中属性名和值的大小写敏感性 由文档语言决定。
如需不受文档语言规则影响,
以ASCII
不区分大小写方式匹配属性值,
可在属性选择器闭合方括号(])前加上 i 标识符。
当有此标志时,
用户代理必须以ASCII
不区分大小写方式匹配属性值(即 [a-z] 和 [A-Z] 视为等价)。
或者,属性选择器可以在闭合方括号(])前加上 s 标识符;
此时用户代理必须以区分大小写的方式匹配属性值,
采用 “完全相同” 语义 [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中的默认属性值
属性选择器表示文档树中的属性值。 文档树如何构建并不在Selectors规范范围内。 在某些文档格式中,默认属性值可在DTD或其他地方定义,但只有当这些属性值出现在文档树中时属性选择器才能选中它们。选择器的设计应确保无论这些默认值是否加入到文档树中都能正常工作。
例如,XML UA可以但不必须 读取DTD的“外部子集”,但必须查找文档“内部子集”中的默认属性值。 (详见[XML10]对于这些子集的定义。) 取决于UA,定义在DTD外部子集的默认属性值 可能会,也可能不会出现在文档树中。
支持XML命名空间的UA可以但不必须利用其命名空间知识, 将默认属性值视作已存在于文档中(例如,XHTML UA不要求依赖其内置的XHTML DTD知识。关于XML 1.0中命名空间的细节,见[XML-NAMES])。
注意: 实现通常会选择忽略外部子集。这与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 } /* class~=pastoral 的 H1 元素 */
根据这些规则,下方第一个 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类型属性;
无论文档语言如何,
ID类型属性都能用于唯一标识它所归属的元素。
在HTML中,所有ID属性都名为id;
XML应用可以为ID属性命名为其它名字,
但相同的唯一性限制依然适用。
元素的哪个属性被视为“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时,用户代理可能不会总是读取DTD,因此有时无法得知元素的ID属性(但用户代理有时可以基于命名空间特定知识判断某命名空间下的ID属性)。如果样式表作者知道或怀疑UA可能无法识别某元素的ID,应该优先用普通属性选择器:[name=p371],而不是#p371。
如果某元素拥有多个ID属性,则在ID选择器语义下,这些属性都应被视为该元素的ID。 这种情形可能由于混用xml:id、DOM3 Core、XML DTD以及命名空间相关知识等手段实现。
匹配怪异模式 文档时,ID需ASCII不区分大小写匹配; 其它情况下,ID选择器均区分大小写,仅匹配完全一样的ID值。 [INFRA]
7. 语言类伪类
7.1. 方向性伪类::dir()
测试
- dir-pseudo-in-has.html (live test) (source)
- dir-pseudo-on-bdi-element.html (live test) (source)
- dir-pseudo-on-input-element.html (live test) (source)
- dir-pseudo-update-document-element.html (live test) (source)
- dir-selector-auto-direction-change-001.html (live test) (source)
- dir-selector-auto.html (live test) (source)
- dir-selector-change-001.html (live test) (source)
- dir-selector-change-002.html (live test) (source)
- dir-selector-change-003.html (live test) (source)
- dir-selector-change-004.html (live test) (source)
- dir-selector-ltr-001.html (live test) (source)
- dir-selector-ltr-002.html (live test) (source)
- dir-selector-ltr-003.html (live test) (source)
- dir-selector-querySelector.html (live test) (source)
- dir-selector-rtl-001.html (live test) (source)
- dir-selector-white-space-001.html (live test) (source)
- dir-style-01a.html (live test) (source)
- dir-style-01b.html (live test) (source)
- dir-style-02a.html (live test) (source)
- dir-style-02b.html (live test) (source)
- dir-style-03a.html (live test) (source)
- dir-style-03b.html (live test) (source)
- dir-style-04.html (live test) (source)
- part-dir.html (live test) (source)
:dir()
伪类允许作者编写
基于元素方向性(由文档语言决定)表示元素的选择器。
例如,[HTML5]定义了
如何确定元素的方向性,
它会基于dir属性、周围文本和其他因素的组合进行确定。
另一个例子是,国际化标签集[ITS20]中的its:dir和dirRule元素
可以在[XML10]中定义元素的方向性。
:dir()伪类 不会根据样式状态进行选择,比如CSS的direction属性 不影响是否能匹配该伪类。
伪类:dir(ltr)表示方向为从左到右(ltr)的元素。伪类:dir(rtl)表示方向为从右到左(rtl)的元素。:dir()的参数必须是单个标识符,否则该选择器无效。标识符与括号之间可以有空白。除ltr和rtl外,其他值不会导致无效,但不会匹配任何内容。(如果未来的标记规范定义了其它方向性,则选择器可能会扩展支持相应的值。)
:dir(C)与[dir=C]的区别在于,[dir=C]仅对元素上的指定属性做比较,
而:dir(C)伪类会利用UA对文档语义的理解进行比较。例如,在HTML中,元素的方向性是继承的,子元素没有dir属性时会继承最近祖先中有效的dir属性方向。再比如,在HTML中,
匹配[dir=auto]的元素会根据内容实际解析方向性匹配:dir(ltr)或:dir(rtl)。[HTML5]
7.2. 语言伪类::lang()
测试
- css3-selectors-lang-001.html (live test) (source)
- css3-selectors-lang-002.html (live test) (source)
- css3-selectors-lang-004.html (live test) (source)
- css3-selectors-lang-005.html (live test) (source)
- css3-selectors-lang-006.html (live test) (source)
- css3-selectors-lang-007.html (live test) (source)
- css3-selectors-lang-008.html (live test) (source)
- css3-selectors-lang-009.html (live test) (source)
- css3-selectors-lang-010.html (live test) (source)
- css3-selectors-lang-011.html (live test) (source)
- css3-selectors-lang-012.html (live test) (source)
- css3-selectors-lang-014.html (live test) (source)
- css3-selectors-lang-015.html (live test) (source)
- css3-selectors-lang-016.html (live test) (source)
- css3-selectors-lang-021.html (live test) (source)
- css3-selectors-lang-022.html (live test) (source)
- css3-selectors-lang-024.html (live test) (source)
- css3-selectors-lang-025.html (live test) (source)
- css3-selectors-lang-026.html (live test) (source)
- css3-selectors-lang-027.html (live test) (source)
- css3-selectors-lang-028.html (live test) (source)
- css3-selectors-lang-029.html (live test) (source)
- css3-selectors-lang-030.html (live test) (source)
- css3-selectors-lang-031.html (live test) (source)
- css3-selectors-lang-032.html (live test) (source)
- css3-selectors-lang-034.html (live test) (source)
- css3-selectors-lang-035.html (live test) (source)
- css3-selectors-lang-036.html (live test) (source)
- css3-selectors-lang-041.html (live test) (source)
- css3-selectors-lang-042.html (live test) (source)
- css3-selectors-lang-044.html (live test) (source)
- css3-selectors-lang-045.html (live test) (source)
- css3-selectors-lang-046.html (live test) (source)
- css3-selectors-lang-047.html (live test) (source)
- css3-selectors-lang-048.html (live test) (source)
- css3-selectors-lang-049.html (live test) (source)
- css3-selectors-lang-050.html (live test) (source)
- css3-selectors-lang-051.html (live test) (source)
- css3-selectors-lang-052.html (live test) (source)
- css3-selectors-lang-054.html (live test) (source)
- css3-selectors-lang-055.html (live test) (source)
- css3-selectors-lang-056.html (live test) (source)
- lang-pseudo-class-across-shadow-boundaries.html (live test) (source)
- lang-pseudo-class-disconnected.html (live test) (source)
- lang-pseudo-class-empty-attribute.xhtml (live test) (source)
- part-lang.html (live test) (source)
- lang-000.html (live test) (source)
- lang-001.html (live test) (source)
- lang-002.html (live test) (source)
- lang-003.html (live test) (source)
- lang-004.html (live test) (source)
- lang-005.html (live test) (source)
- lang-006.html (live test) (source)
- lang-007.html (live test) (source)
- lang-008.html (live test) (source)
- lang-009.html (live test) (source)
- lang-010.html (live test) (source)
- lang-011.html (live test) (source)
- lang-012.html (live test) (source)
- lang-013.html (live test) (source)
- lang-014.html (live test) (source)
- lang-015.html (live test) (source)
- lang-016.html (live test) (source)
- lang-017.html (live test) (source)
- lang-018.html (live test) (source)
- lang-019.html (live test) (source)
- lang-020.html (live test) (source)
- lang-021.html (live test) (source)
- lang-022.html (live test) (source)
- lang-023.html (live test) (source)
- lang-024.html (live test) (source)
- lang-025.html (live test) (source)
如果文档语言规定了如何确定元素的(人类)内容语言, 就可以基于内容语言来编写选择器。 :lang() 伪类可接收一个或多个由逗号分隔的语言范围, 表示其内容语言在实参列出的任意语言中的元素。 :lang()里每个语言范围 必须是合法的CSS <ident> 或 <string>。 (因此如带星号的语言范围,需转义或写成字符串,例如:lang(\*-Latn)或:lang("*-Latn")。)
注意: 元素的内容语言 由文档语言定义。
如HTML [HTML5]中,内容语言由lang属性、
meta元素的信息,
以及协议(如HTTP头)共同决定;
XML语言可用xml:lang属性指明元素的语言信息。[XML10]
若元素的内容语言,用BCP 47语法表示时, 可在语言范围下执行扩展筛选操作(见[RFC4647]第3.3.2节)。 在扩展筛选操作前,内容语言和语言范围都需标准化,并按[RFC5646]第4.5节转为extlang形态。匹配时,ASCII范围内不区分大小写。
进行该比较时,语言范围不必是合法的语言代码。
星号"*")
不会匹配未标注语言(如lang="")的元素,
只匹配被标注为undetermined(如lang=und)的元素。
以空字符串为
注意: 推荐文档和协议用[BCP47]或其后继标准的代码指明语言,
对于基于XML的格式应用xml:lang属性。[XML10] 见 “FAQ: Two-letter or three-letter
language codes.”
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)。
注意: 通配符语言匹配和逗号分隔列表是Level 4新增内容。
8. 位置伪类
8.1. 超链接伪类::any-link
:any-link
伪类表示作为超链接源锚点的元素。
例如,在[HTML5]中,
任何带有
a
或
area
元素,且带有
href
属性的,都是超链接,
因此可以匹配:any-link。
如果一个元素可以被:link或:visited匹配,
那么它就被匹配,等价于:is(:link, :visited)。
8.2. 链接历史伪类::link 和 :visited
测试
- caret-color-visited-inheritance.html (live test) (source)
- text-emphasis-visited-inheritance.html (live test) (source)
- text-fill-color-visited-inheritance.html (live test) (source)
- text-stroke-color-visited-inheritance.html (live test) (source)
- visited-in-visited-compound.html (live test) (source)
- visited-inheritance.html (live test) (source)
- visited-nested.html (live test) (source)
- visited-part-crash.html (live test) (source)
用户代理通常会将未访问过的超链接与 已访问过的超链接以不同方式显示。 Selectors 提供了伪类 :link 和 :visited 来区分二者:
两种状态互斥。
一段时间后, 用户代理可能将已访问链接 恢复为(未访问的):link状态。
:visited 伪类涉及明显的隐私问题 —— 让任意网站知道你访问过哪些其它网站 在多种场景下都是有问题的 —— 因此,用户代理在实现:visited时必须保障用户隐私。
-
精确跟踪某个origin本可观测到的历史记录项, 仅当访问历史可从该站点origin观测到时才让链接匹配:visited。 具体做法见附录C:示例隐私保护 :visited 限制。
-
允许所有origin下链接都能匹配:visited, 但严格限制可应用的样式 以及诸如
getComputedStyle()之类样式查询API能返回的信息, 以防止网站通过检测样式区分:link或:visited来观察用户历史。 (该方法见 MDN, 也是以往浏览器的实现方式, 但并不完美;有多种方法能让恶意页面仍可推断历史信息。)
8.3. 目标伪类::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) }
注意: 本规范早期定义过:target-within伪类, 其作用类似于:focus-within。 后被移除,建议用:has(:target)代替, 新写法基本能满足相同应用场景。
8.4. 参考元素伪类::scope
在某些场景下,选择器的匹配是
以一个或多个作用域根为依据进行的,
比如在 [DOM] 里调用 querySelector() 方法时。
:scope
伪类用来代表这个作用域根,
它可以是真正的元素,
也可以是虚拟的(比如 DocumentFragment)。
如果没有作用域根, :scope就代表 该元素所在树的根节点 (等价于 :host 在shadow tree中, 或其它情况下的 :root)。 若规范希望此伪类只匹配具体元素而非树根, 需自行定义作用域根的含义。
虚拟作用域根 是代表文档片段根的某种对象, 可在选择器中用来描述其它元素与该作用域根的关系, 并作为其代表的文档片段中所有根元素的父节点。 虚拟作用域根是无特征的,不能作为选择器对象。
DocumentFragment
df,
那么 df. querySelectorAll( ":scope > .foo" )
会匹配文档片段里所有“顶层”的.foo元素
(那些直接以文档片段为parentNode的元素)。
但 df
不会匹配到任何内容,
因为文档片段本身不能作为选择器对象。
9. 用户操作伪类
交互式用户界面有时会根据用户操作改变渲染效果。 Selectors 提供了若干用户操作伪类,可用于选中用户正在操作的元素。 (在非交互式用户代理中,这些伪类语法有效,但不会选中任何元素。)
用户操作伪类之间不是互斥的。 元素可以同时匹配多个此类伪类。
有些用户操作伪类, 除了可匹配具有该属性的具体元素外, 还可匹配这些元素的祖先节点::hover、:active、:focus-within。 具体来说,这些伪类若匹配一个元素, 也会同时匹配其 扁平树祖先, 直到遇到第一个 顶层元素 或 根元素为止(二者遇到先者为准)。
注意: 如何进行命中测试以判断本节伪类是否适用, 目前尚未详细定义, 未来会有规范补充。
9.1. 指针悬停伪类::hover
测试
- hover-001-manual.html (manual test) (source)
- hover-002.html (live test) (source)
- remove-hovered-element.html (live test) (source)
:hover 伪类在用户用指针设备 指定某个元素(或伪元素)时生效, 但不一定意味着该元素被激活。 例如,视觉用户代理可在光标(鼠标指针)悬停于由该元素生成的盒子上时应用此伪类。 由于硬件限制无法侦测悬停的交互式用户代理 (如无法检测悬停的笔触控设备) 依然是合规的; 这种情况下,选择器在该UA中永远无法匹配。
如果某元素的:hover后代(在扁平树中,包括非元素节点,如文本节点),也满足上述条件,则该元素同样匹配。
文档语言可定义元素如何额外匹配:hover。
例如,[HTML5]定义,被label悬停时,相关控件元素也会匹配
:hover。
注意: 由于:hover状态可能因其子项被指针设备指定而应用于元素, 这样会导致:hover应用于并不处于指针下的元素。
9.2. 激活伪类::active
:active 伪类 在元素被用户“激活”时生效, “激活”由宿主语言定义; 例如,超链接被触发时该伪类生效。
此外,:active伪类还在任何元素(或伪元素)生成的盒子 被指针设备主动指示(处于“按下”状态)时生效, 比如用户按下主鼠标键但尚未松开、 或手指正在触摸屏幕时。
注意: [HTML5]定义了HTML元素被激活的具体条件。
如果某元素的:active后代(在扁平树中,包括非元素节点,如文本节点)满足上述条件,则该元素同样匹配。
9.3. 输入焦点伪类::focus
测试
:focus 伪类在元素(或伪元素)具有焦点时生效 (可接受键盘或其它输入)。
能获取:focus的元素, 可能受文档语言或实现细节限制。 例如,[HTML]规定了一组 可聚焦区域。
文档语言可以定义元素如何额外匹配:focus, 但:focus伪类不得 自动传递到父元素——如果需匹配父级,请使用:focus-within。 (:focus仍可因其它机制传递到父元素, 但仅因是父元素不能自动生效。)
作者希望将:focus从表单控件传递到其关联的
label
元素;
主要反对理由似乎是实现难度大。
见CSSWG issue (CSS) 和 WHATWG issue (HTML)。
9.4. 焦点可见伪类::focus-visible
测试
- focus-visible-001.html (live test) (source)
- focus-visible-002.html (live test) (source)
- focus-visible-003.html (live test) (source)
- focus-visible-004.html (live test) (source)
- focus-visible-005.html (live test) (source)
- focus-visible-006.html (live test) (source)
- focus-visible-007.html (live test) (source)
- focus-visible-008.html (live test) (source)
- focus-visible-009.html (live test) (source)
- focus-visible-010.html (live test) (source)
- focus-visible-011.html (live test) (source)
- focus-visible-012.html (live test) (source)
- focus-visible-013.html (live test) (source)
- focus-visible-014.html (live test) (source)
- focus-visible-015.html (live test) (source)
- focus-visible-016.html (live test) (source)
- focus-visible-017-2.html (live test) (source)
- focus-visible-017.html (live test) (source)
- focus-visible-018-2.html (live test) (source)
- focus-visible-018.html (live test) (source)
- focus-visible-019.html (live test) (source)
- focus-visible-020.html (live test) (source)
- focus-visible-021.html (live test) (source)
- focus-visible-023.html (live test) (source)
- focus-visible-024.html (live test) (source)
- focus-visible-025.html (live test) (source)
- focus-visible-026.html (live test) (source)
- focus-visible-027.html (live test) (source)
- focus-visible-028.html (live test) (source)
- focus-visible-script-focus-001.html (live test) (source)
- focus-visible-script-focus-004.html (live test) (source)
- focus-visible-script-focus-005.html (live test) (source)
- focus-visible-script-focus-008-b.html (live test) (source)
- focus-visible-script-focus-008.html (live test) (source)
- focus-visible-script-focus-009.html (live test) (source)
- focus-visible-script-focus-010.html (live test) (source)
- focus-visible-script-focus-011.html (live test) (source)
- focus-visible-script-focus-012.html (live test) (source)
- focus-visible-script-focus-013.html (live test) (source)
- focus-visible-script-focus-014.html (live test) (source)
- focus-visible-script-focus-015.html (live test) (source)
- focus-visible-script-focus-018.html (live test) (source)
- focus-visible-script-focus-019.html (live test) (source)
- focus-visible-script-focus-020.html (live test) (source)
- parse-focus-visible.html (live test) (source)
虽然 :focus 伪类总是匹配 当前被聚焦的元素, 但用户代理只在部分情形下会明确指示焦点(例如绘制“焦点环”), 实际上会采用各种启发式策略, 仅在对用户最有帮助时才可见地显示焦点。 :focus-visible 伪类 只在这些场合下匹配被聚焦的元素(或伪元素), 从而让作者可以更改焦点指示器的外观, 而不会改变焦点指示器何时出现。
:root{ --focus-gold : #ffbf47; } :focus-visible{ outline : 3 px solidvar ( --focus-gold); } a:focus-visible{ background-color : var ( --focus-gold); }
-
如果用户表达了始终可见焦点的偏好 (如系统设置或浏览器设置),则无论其他因素如何都应指示焦点。 (另一种做法是用户代理始终显示自己的焦点指示器,无视作者样式。)
-
如果用户通过键盘或其他非指针设备与页面交互,指示焦点。 (这意味着键盘操作可能改变该伪类是否匹配, 即使它对:focus无影响)。
-
如果用户通过指针设备(鼠标、触屏等)与页面交互, 且聚焦元素不支持键盘输入, 则不指示焦点。
-
如果前一个聚焦元素指示了焦点, 而脚本令焦点转移,则新获得焦点的元素也应指示焦点。
反之,若前一个聚焦元素未指示焦点, 且脚本令焦点转移, 则新获得焦点的元素也不指示焦点。
-
如果新显示的元素自动获得焦点 (比如新对话框里的action按钮), 那么该元素也应指示焦点。
用户代理也应默认用:focus-visible指定焦点样式, 这样样式作者在用:focus-visible时无需额外禁用原有 :focus样式。
9.5. 焦点容器伪类::focus-within
测试
- focus-within-001.html (live test) (source)
- focus-within-002.html (live test) (source)
- focus-within-003.html (live test) (source)
- focus-within-004.html (live test) (source)
- focus-within-005.html (live test) (source)
- focus-within-006.html (live test) (source)
- focus-within-007.html (live test) (source)
- focus-within-008.html (live test) (source)
- focus-within-009.html (live test) (source)
- focus-within-010.html (live test) (source)
- focus-within-011.html (live test) (source)
- focus-within-012.html (live test) (source)
- focus-within-013.html (live test) (source)
- focus-within-display-none-001.html (live test) (source)
- focus-within-focus-move.html (live test) (source)
- focus-within-removal.html (live test) (source)
- focus-within-shadow-001.html (live test) (source)
- focus-within-shadow-002.html (live test) (source)
- focus-within-shadow-003.html (live test) (source)
- focus-within-shadow-004.html (live test) (source)
- focus-within-shadow-005.html (live test) (source)
- focus-within-shadow-006.html (live test) (source)
:focus-within 伪类 适用于任何匹配 :focus 伪类的元素(或伪元素), 以及那些在扁平树中,其后代节点(包括非元素节点,如文本节点) 满足 :focus 匹配条件的元素(或伪元素)。
10. 资源状态伪类
本章中的伪类适用于表示已加载资源的元素, 尤其是图片/视频, 并允许作者根据其状态的一些特性进行选择。
10.1. 媒体播放状态::playing、:paused 和 :seeking 伪类
:playing 伪类表示一个可以“播放”或“暂停”的元素, 当前正处于“播放”状态时适用。 (包括元素明确处于播放中, 也包括因非用户主动意图而暂时停止、但该原因消除后会自动继续播放的情形, 如“缓冲”或“卡顿”状态。)
:paused 伪类表示一个可以“播放”或“暂停”的元素, 当前正处于“暂停”状态(即不是“播放”)。 (包括明确“暂停”状态, 以及其它非播放状态,比如“已加载但尚未激活”等。)
:seeking
伪类表示一个可以“跳播”的元素,
当前正处于“跳播”(seeking)状态时适用。
(对于 HTML 的
audio
和
video
元素,参见HTML
§ 4.8.11.9 跳播。)
10.2. 媒体加载状态::buffering 和 :stalled 伪类
测试
:buffering 伪类表示 一个可以“播放”或“暂停”的元素, 当该元素无法继续播放, 因为它正在主动尝试获取媒体数据, 但尚未获得足够数据以恢复播放时匹配。 (注意,当元素处于“缓冲”状态时,仍然被视为“播放”中。 只要:buffering匹配该元素,:playing 也会匹配该元素。)
:stalled
伪类表示一个元素
当该元素无法继续播放,
因为它正在主动尝试获取媒体数据,
但在一段时间内未能接收到任何数据时匹配。
对于HTML中的
audio
和
video
元素,
这段时间指的是媒体元素 stall 超时时间。[HTML]
(注意,与:buffering伪类类似,
当元素处于“卡顿”状态时,仍然被视为“播放”中。
只要:stalled匹配该元素,:playing 也会匹配该元素。)
10.3. 声音状态::muted 和 :volume-locked 伪类
:muted
伪类表示
可发声元素,
当前处于“静音”(强制无声)状态。
(对于HTML的
audio
和
video
元素,详见muted。[HTML])
:volume-locked 伪类表示
可发声元素,
当前其音量被UA或用户“锁定”,
页面作者无法更改其音量。
(对于HTML的
audio
和
video
元素,
见关于设置元素实际媒体音量的算法。[HTML])
11. 元素显示状态伪类
11.1. 折叠状态::open 伪类
测试
:open 伪类表示具有“打开”和“关闭”两种状态的元素, 当前正处于“打开”状态。
“打开”与“关闭”具体意义由宿主语言决定,
典型示例有 HTML 的
details、
select、
dialog、
以及
input
元素,
它们都可通过切换“打开”显示更多内容
(对dialog而言是显示全部内容)。
注意: “打开”或“关闭”是语义状态。 即使元素当前不可见 (如被设置visibility: collapse, 或属于display: none子树), 也可能处于“打开”状态并匹配:open。
注意: 将来可能会补充":closed"伪类, 目前正在确定支持:open的所有情形。
11.2. 弹出层状态::popover-open 伪类
:popover-open 伪类表示具有 “popover-showing”(弹出层显示)和“popover-hidden” (弹出层隐藏)两种状态的元素, 当前正处于“popover-showing”状态时匹配。
注意: 这与 :open 不同,因为一个元素可以既有自身的open/closed状态, 也有与弹出层相关联的popover-showing/ popover-hidden状态。
“popover-showing”与“popover-hidden”
状态的具体含义由宿主语言决定,
但以HTML的
popover
属性和相关的
弹出层可见性状态
为例进行说明。
11.3. 模态(独占交互)状态::modal 伪类
:modal 伪类表示 当前处于排他交互状态(即在该元素被关闭前,不能与其外部内容交互)的元素。 多个元素可以同时处于:modal状态, 但只能有一个元素是激活的(即可以接受输入)。
dialog
元素在通过showModal()
API打开时就是:modal。
类似地,:fullscreen元素在通过requestFullscreen()
API打开时也会是:modal,
因为这类情形下也会阻止对页面其它部分的操作。
11.4. 全屏展示状态::fullscreen 伪类
:fullscreen 伪类表示 以一种占据大部分(通常为全部)屏幕的模式显示的元素, 如Fullscreen API定义的全屏模式。[FULLSCREEN]
11.5. 画中画展示状态::picture-in-picture 伪类
:picture-in-picture 伪类表示 以一种占据大部分(通常为全部)视口且视口限制在屏幕的某一部分、叠加显示于其他内容之上的模式显示的元素, 例如使用 Picture-in-Picture API 的情形。[picture-in-picture]
12. 输入伪类
本节中的伪类主要适用于接收用户输入的元素, 例如HTML的input元素。
12.1. 输入控件状态
12.1.1. :enabled 和 :disabled 伪类
:enabled 伪类表示 处于启用状态的用户界面元素; 这些元素必须有对应的禁用状态。
相反,:disabled 伪类表示 处于禁用状态的用户界面元素; 这些元素必须有对应的启用状态。
什么是启用状态、禁用状态,以及什么是用户界面元素,取决于宿主语言。在典型的文档中,大多数元素既不是 :enabled 也不是 :disabled。 例如,[HTML5] 规定 非禁用的交互元素 为 :enabled, 而所有这些元素中被 明确禁用 的则为 :disabled。
注意: 可能影响用户与给定界面元素交互能力的 CSS 属性不会影响其是否匹配 :enabled 或 :disabled; 如 display 和 visibility 属性都不会影响元素的启用/禁用状态。
12.1.2. 可变性伪类::read-only 和 :read-write
测试
若元素可由用户更改(具体由文档语言定义), 则该元素匹配 :read-write。 否则即为 :read-only。
例如,在 [HTML5] 中,
未禁用且非readonly的
<input> 元素会被视为:read-write;
有 contenteditable 属性且值为 true 的元素亦同理。
12.1.3. 占位符显示伪类::placeholder-shown
测试
- placeholder-shown.html (live test) (source)
- placeholder-shown.html (live test) (source)
- selector-placeholder-shown-emptify-placeholder.html (live test) (source)
- selector-placeholder-shown-type-change-001.html (live test) (source)
- selector-placeholder-shown-type-change-002.html (live test) (source)
- selector-placeholder-shown-type-change-003.html (live test) (source)
输入元素有时会显示占位符文本,
给用户输入内容时提供提示。
例如,见 [HTML5] 中的 placeholder
属性。
:placeholder-shown 伪类
匹配正显示此类占位符文本的输入元素,
不论该文本是由属性、真实元素,还是用户代理其它方式给出的。
placeholder
属性在
input
和
textarea
元素上
都可提供占位符文本。
因此只要显示了这样的占位符文本,:placeholder-shown 类就会生效。
12.1.4. 自动填充伪类::autofill
:autofill 伪类匹配 已被用户代理自动填充且未被用户修改过的输入元素。
12.1.5. 默认选项伪类::default
:default 伪类应用于在一组相似元素中处于默认状态的一个或多个UI元素。通常用于上下文菜单项、按钮和下拉列表/菜单等。
比如,在一组按钮中默认提交使用的按钮即为默认选项。
另一个例子是弹出菜单中默认选中的选项。
在多选组(如比萨配料选项)中,多个元素可以同时匹配:default。
举例来说,[HTML5] 规定:default 匹配 表单的“默认按钮”、<select>中初始被选中的<option>(们),以及一些其它元素。
12.2. 输入值状态
12.2.1. 选中项伪类: :checked、 :unchecked 和 :indeterminate
单选框和复选框等元素可被用户切换状态, 有些菜单项在用户选择时会处于“选中”状态。 这些状态由输入值伪类来反映。
当这些元素被切换为“开”时,
:checked
伪类将会生效。
例如,[HTML5] 规定,被选中的复选框、
单选按钮和已选中的 <option> 元素 都会匹配 :checked。
类似地,当这些元素被切换为“关”时,
:unchecked
伪类将会生效。
如果某元素可以匹配:checked或:unchecked,但现在既不是"打开"也不是"关闭", 则应用:indeterminate伪类。:indeterminate 也匹配没有“选中”概念, 但“值”正处于非确定状态的元素, 比如表示进度未知的进度条(meter/progress)。
这三种伪类互斥; 同一时刻元素最多只能匹配其中一个。 (有些元素甚至三者都不匹配, 因为它们没有“选中”语义。) 如果宿主语言中“indeterminate”不是“checked/unchecked”的互斥分组 (例如HTML中,checkbox的indeterminate和checked是两个独立布尔值), 则就伪类匹配而言,当元素处于indeterminate状态时优先生效,不管checked/unchecked为何值。
-
当复选框的
indeterminate属性为真时匹配:indeterminate; 否则,根据checked属性匹配:checked或:unchecked。 -
单选按钮
checked属性为真时匹配:checked; 否则,若处于某个拥有:checked单选的分组中,则匹配:unchecked; 否则(即checked属性为假且所在分组无任何选中),则匹配:indeterminate。 -
option元素在select内会根据selected属性匹配:checked或:unchecked。 (永远不会匹配:indeterminate。) -
progress元素如果没有value属性,则匹配:indeterminate
这些输入值伪类本质上是动态的,
能被用户操作改变,
由于也可能依赖于文档中的语义属性(如[HTML5]的selected和checked),
所以适用于所有媒介。
12.3. 输入值有效性检查
12.3.1. 有效性伪类::valid 和 :invalid
若元素内容或值符合文档语言定义的数据有效性语义,则为:valid,否则为:invalid。 (如 [XFORMS11] 或 [HTML5])。 没有数据有效性语义的元素既不会是:valid,也不会是:invalid。
注意: 有约束但总是有效的元素和没有有效性语义的元素是不同的。
前者总会匹配:valid,
后者二者都不匹配。
例如HTML中,<input type="text">没有约束时总是:valid;
p元素没有有效性语义,因而不会匹配这两个伪类。
12.3.2. 区间伪类::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",也为:out-of-range。
12.3.3. 必选/可选伪类::required 和 :optional
测试
当表单元素在所属表单有效提交前分别需要填写或可选填写时, 该元素为 :required 或 :optional。 不是表单元素的,不属于必填也不属于可选。
12.3.4. 用户交互伪类::user-valid 和 :user-invalid
测试
:user-invalid 与 :user-valid 伪类, 分别表示输入内容错误或正确的元素, 但只有在用户与其发生过明显交互之后才会生效。 它们的目的是帮助用户识别输入中的错误。
这些伪类至少应在用户尝试提交表单之后, 并在用户再次操作该输入元素 或重置表单之前,匹配相应元素。 当然,在需要高亮错误以提示用户时, 也可以在其他时机匹配。 例如,:user-invalid 可以在用户更改输入值且 焦点离开元素后开始匹配:invalid 输入元素, 或仅在用户成功修正输入后才停止匹配。
宿主语言可定义更精确的匹配规则, 也可遵循平台惯例; 否则行为由UA自定。 无论如何, :user-invalid 伪类只可匹配:invalid元素; :user-valid 伪类只可匹配:valid元素。 有关HTML元素的具体规则参见HTML规范。[HTML]
input
元素在页面加载时就会匹配:invalid伪类
(因为该
input的初始值已违反其最大值约束),
但在用户与该输入框有显著交互或尝试提交包含它的表单之前,
它不会匹配:user-invalid。
<form>
<label>
Volume:
<input name='vol' type=number min=0 max=10 value=11>
</label>
...
</form>
13. 树结构伪类
Selectors 引入了结构伪类的概念, 允许基于文档树中不能用其他简单选择器或组合器 表达的额外信息进行选择。
独立文本以及其它非元素节点在计算 某元素在其父节点子元素列表中的位置时不计入在内。 元素在父节点子元素列表中的位置编号 从 1 开始。
13.1. :root 伪类
:root 伪类表示作为文档根节点的元素。
例如,在 DOM 文档中,
:root
伪类会匹配文档元素。
在 HTML 中,这通常是
html
元素
(除非脚本修改了文档结构)。
13.2. :empty 伪类
:empty 伪类表示 一个没有任何子节点的元素, 只允许(可选地)包含文档空白字符。 以文档树的角度, 只需考虑元素节点和内容节点 (如[DOM]文本节点、实体引用) 且其数据长度大于零时,才会影响该元素是否为空; 注释、处理指令和其它节点 均不影响该元素是否视为empty。
p
元素的有效表达:
<p></p> <p> <p> </p> <p> <!-- comment --></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 文本节点—— 这样作者认为“空”的元素就可以用此选择器按预期选中。
13.3. 子项索引伪类
测试
- child-indexed-no-parent.html (live test) (source)
- child-indexed-pseudo-class.html (live test) (source)
- negated-nth-child-when-ancestor-changes.html (live test) (source)
- negated-nth-last-child-when-ancestor-changes.html (live test) (source)
- nth-child-containing-ancestor.html (live test) (source)
- nth-child-in-shadow-root.html (live test) (source)
- nth-child-of-attr-largedom.html (live test) (source)
- nth-child-of-attr.html (live test) (source)
- nth-child-of-class-prefix.html (live test) (source)
- nth-child-of-class.html (live test) (source)
- nth-child-of-has.html (live test) (source)
- nth-child-of-id-prefix.html (live test) (source)
- nth-child-of-ids.html (live test) (source)
- nth-child-of-in-ancestor.html (live test) (source)
- nth-child-of-in-is.html (live test) (source)
- nth-child-of-in-shadow-root.html (live test) (source)
- nth-child-of-is.html (live test) (source)
- nth-child-of-pseudo-class.html (live test) (source)
- nth-child-of-sibling.html (live test) (source)
- nth-child-when-ancestor-changes.html (live test) (source)
- nth-child-when-sibling-changes.html (live test) (source)
- nth-child-whole-subtree.html (live test) (source)
- nth-last-child-containing-ancestor.html (live test) (source)
- nth-last-child-in-shadow-root.html (live test) (source)
- nth-last-child-of-attr.html (live test) (source)
- nth-last-child-of-class-prefix.html (live test) (source)
- nth-last-child-of-class.html (live test) (source)
- nth-last-child-of-has.html (live test) (source)
- nth-last-child-of-id-prefix.html (live test) (source)
- nth-last-child-of-ids.html (live test) (source)
- nth-last-child-of-in-ancestor.html (live test) (source)
- nth-last-child-of-in-is.html (live test) (source)
- nth-last-child-of-in-shadow-root.html (live test) (source)
- nth-last-child-of-is.html (live test) (source)
- nth-last-child-of-pseudo-class.html (live test) (source)
- nth-last-child-of-sibling.html (live test) (source)
- nth-last-child-when-ancestor-changes.html (live test) (source)
- nth-last-child-when-sibling-changes.html (live test) (source)
- nth-child-and-nth-last-child.html (live test) (source)
- nth-child-of-attribute.html (live test) (source)
- nth-child-of-classname-002.html (live test) (source)
- nth-child-of-classname.html (live test) (source)
- nth-child-of-complex-selector-many-children-2.html (live test) (source)
- nth-child-of-complex-selector-many-children.html (live test) (source)
- nth-child-of-complex-selector.html (live test) (source)
- nth-child-of-compound-selector.html (live test) (source)
- nth-child-of-has.html (live test) (source)
- nth-child-of-nesting.html (live test) (source)
- nth-child-of-no-space-after-of.html (live test) (source)
- nth-child-of-not.html (live test) (source)
- nth-child-of-nth-child.html (live test) (source)
- nth-child-of-pseudo.html (live test) (source)
- nth-child-of-tagname.html (live test) (source)
- nth-child-of-universal-selector.html (live test) (source)
- nth-child-specificity-1.html (live test) (source)
- nth-child-specificity-2.html (live test) (source)
- nth-child-specificity-3.html (live test) (source)
- nth-child-specificity-4.html (live test) (source)
- nth-child-spurious-brace-crash.html (live test) (source)
- nth-last-child-invalid.html (live test) (source)
- nth-last-child-of-classname.html (live test) (source)
- nth-last-child-of-complex-selector.html (live test) (source)
- nth-last-child-of-compound-selector.html (live test) (source)
- nth-last-child-of-nesting.html (live test) (source)
- nth-last-child-of-no-space-after-of.html (live test) (source)
- nth-last-child-of-style-sharing-1.html (live test) (source)
- nth-last-child-of-style-sharing-2.html (live test) (source)
- nth-last-child-of-tagname.html (live test) (source)
- nth-last-child-specificity-1.html (live test) (source)
- nth-last-child-specificity-2.html (live test) (source)
- nth-last-child-specificity-3.html (live test) (source)
- nth-last-child-specificity-4.html (live test) (source)
- sharing-in-svg-use.html (live test) (source)
- parse-anplusb.html (live test) (source)
本节定义的伪类可以根据元素在其包括自身的兄弟节点中的索引来选中元素。
注意: Selectors 3 描述这些选择器是按照 元素在父节点子列表中的索引来选中的。 (这个描述仍然保留在本节标题及一些伪类的命名中。) 由于没必要把没有父节点或父节点不是元素的情形排除在外, 规范已改写为以元素在兄弟节点间的相对索引为准。
13.3.1. :nth-child() 伪类
测试
:nth-child(An+B [of S]? ) 伪类表示 那些在其匹配选择器列表 S(属于包含自身的兄弟节点且匹配选择器列表 S)中,处于An+B序号的元素。 S 是<complex-real-selector-list>。 如果省略S,则默认值为*|*。
An+B记法及其解释定义见 CSS Syntax 3 § 6 The An+B microsyntax; 表示任何非负整数 n 时 i = An + B 的任意索引。
注意: 对于此用法,元素列表从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中最特定复杂选择器的专属性。 见 § 15 选择器专属性的计算。 因此S:nth-child(An+B) 和 :nth-child(An+B of S) 尽管行为不同, 其专属性完全一样(见下方示例)。
:nth-child(-n+3 of li.important)
注意这和把选择器放在函数外不同,如:
li.important:nth-child(-n+3)
这个选择器只匹配前3个子项,且它们必须恰好是"important"类的项。
通常,斑马纹表格会用如下CSS:
tr {
background: white;
}
tr:nth-child(even) {
background: silver;
}
但若某些行被隐藏,显示顺序就会错乱,导致同色行相邻。 假设HTML中用[hidden]属性隐藏行,下面CSS可确保无论哪些行隐藏,斑马色仍然交错:
tr {
background: white;
}
tr:nth-child(even of :not([hidden])) {
background: silver;
}
13.3.2. :nth-last-child() 伪类
:nth-last-child(An+B [of S]? ) 伪类 表示那些在其匹配选择器列表S的包括自身的兄弟节点中,从末尾反向计数处于An+B序号的元素。 S为<complex-real-selector-list>。 S省略时默认*|*。
注意: :nth-last-child() 和 :nth-child() 伪类一样, 其专属性为普通伪类专属性加上参数S的专属性。 见 § 15 选择器专属性的计算。
CSS Syntax模块 [CSS3SYN] 定义了An+B记法。
13.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 不是根元素) */
13.3.4. :last-child 伪类
:last-child 伪类 表示在其所有兄弟节点中排最后的元素。 等同于 :nth-last-child(1)。
13.3.5. :only-child 伪类
:only-child 伪类 表示没有兄弟节点的元素。 等价于:first-child:last-child 或 :nth-child(1):nth-last-child(1), 但专属性更低。
13.4. 有类型子项索引伪类
本节中的伪类类似于子项索引伪类, 但它们是基于元素在兄弟节点中与相同类型(标签名)的元素的索引来判断的。
13.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)。
13.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)
13.4.3. :first-of-type 伪类
测试
- first-of-type.html (live test) (source)
- negated-always-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-first-of-type-in-nonsubject-position.html (live test) (source)
- negated-is-always-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-never-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-never-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- of-type-selectors.xhtml (live test) (source)
: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>
13.4.4. :last-of-type 伪类
测试
- negated-always-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-always-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-never-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-last-of-type-invalidation.html (live test) (source)
- negated-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-never-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
:last-of-type 伪类 表示与:nth-last-of-type(1)相同的元素。
13.4.5. :only-of-type 伪类
:only-of-type 伪类 表示与:first-of-type:last-of-type相同的元素。
14. 组合器
14.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]
14.2. 子代组合器 (>)
子代组合器 描述两个元素之间的父子关系。子代组合器由 “大于号”(U+003E,>)字符组成, 用于分隔两个复合选择器。
body子元素的
p 元素:
body > p
下面的例子结合了后代组合器与子代组合器。
div ol>li p
它表示作为
li 元素后代的
p 元素;
li 元素必须是
ol 元素的子元素;
ol 元素又必须是
div 的后代。
注意,这里省略了“>”组合器两侧的可选空白。
关于如何选择某个元素的第一个子元素, 请参阅上面关于:first-child伪类的小节。
14.3.
紧邻兄弟组合器 (+)
测试
紧邻兄弟组合器由“加号” (U+002B, +)字符组成,用于分隔两个复合选择器。 两个复合选择器代表的元素在文档树中有相同的父元素, 且第一个复合选择器所代表的元素紧邻在第二个表示的元素之前。 在判断元素相邻时,非元素节点(如元素间的文本) 会被忽略。
math + p
下面这个选择器与上例类似,只是增加了属性选择器 — 它对
h1 元素增加了 class="opener" 的限制:
h1.opener + h2
14.4.
后续兄弟组合器 (~)
后续兄弟组合器由“波浪号” (U+007E, ~) 字符组成,用于分隔两个复合选择器。 这两个复合选择器对应的元素 具有相同的父节点,且第一个复合选择器所代表的元素在文档树中排在第二个之前(不必紧邻)。
h1 ~ pre
表示紧跟在 h1 后的
pre 元素。它对于如下内容是一个有效但部分的描述:
<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>
15. 选择器专属性(Specificity)的计算
针对某个元素,选择器的 专属性 (specificity) 计算方式如下:
- 统计选择器中的 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]
16. 语法规则
选择器会依据以下语法规则被解析:
<selector-list> = <complex-selector-list>
<complex-selector-list> = <complex-selector>#
<complex-real-selector-list> = <complex-real-selector>#
<compound-selector-list> = <compound-selector>#
<simple-selector-list> = <simple-selector>#
<relative-selector-list> = <relative-selector>#
<relative-real-selector-list> = <relative-real-selector>#
<complex-selector> = <complex-selector-unit> [ <combinator>? <complex-selector-unit> ]*
<complex-selector-unit> = [ <compound-selector>? <pseudo-compound-selector>* ]!
<complex-real-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*
<relative-selector> = <combinator>? <complex-selector>
<relative-real-selector> = <combinator>? <complex-real-selector>
<compound-selector> = [ <type-selector>? <subclass-selector>* ]!
<pseudo-compound-selector> = <pseudo-element-selector> <pseudo-class-selector>*
<simple-selector> = <type-selector> | <subclass-selector>
<combinator> = '>' | '+' | '~' | [ '|' '|' ]
<wq-name> = <ns-prefix>? <ident-token>
<ns-prefix> = [ <ident-token> | '*' ]? '|'
<type-selector> = <wq-name> | <ns-prefix>? '*'
<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> | <legacy-pseudo-element-selector>
<legacy-pseudo-element-selector> = : [before | after | first-line | first-letter]
在解释上述语法时, 适用以下规则:
-
空白字符是禁止的:
-
在 <compound-selector> 或 <complex-selector-unit> 的顶层各组件之间(即禁止出现在 <type-selector> 和 <subclass-selector> 之间,或 <pseudo-element-selector> 和 <pseudo-class-selector> 之间,等等)。
-
在 <type-selector> 或 <class-selector> 的任意组分之间。
-
在 <pseudo-element-selector> 或 <pseudo-class-selector> 中冒号之间,或冒号与 <ident-token> 或 <function-token> 之间。
-
在 <wq-name> 各组分之间。
-
在 <attr-matcher> 各组分之间。
-
在 <complex-selector-unit> 中的 <compound-selector> 或 <pseudo-compound-selector> 之间。
-
在 <combinator> 各组分之间。
如果两个 <complex-selector-unit> 之间省略了 <combinator>,则必须有空白字符隔开。 (这表示用了后代组合器。)
-
- 在 <id-selector> 中, <hash-token> 的值必须是 标识符。
- <pseudo-class-selector> 产生式 不包含 <legacy-pseudo-element-selector>。 (也就是说,:before/等绝不能被解析为伪类, 即使这样做可以让选择器变得有效,比如后面还有其他简单选择器时。)
注意: 一个选择器还受多种更具体的语法约束, 满足上述语法是其有效性的必要但不足条件。 参见 § 3.9 无效选择器与错误处理 以了解选择器解析的额外规则。
注意: 一般来说, 只有当 <pseudo-element-selector> 出现在 最后一个 <compound-selector> 的末尾时才有效。 但某些情况下,它后面也可以跟更多 <pseudo-element-selector> 或 <pseudo-class-selector>; 但这些需要逐个特定说明。 (比如,用户操作伪类 可跟在任意 伪元素 后面, 树相关伪元素可跟在 ::slotted() 伪元素之后。)
四个 Level 2 伪元素(::before、::after、::first-line 和 ::first-letter) 出于兼容历史原因, 可以只用一个英文冒号“:”开头, 使其看起来像一个 <pseudo-class-selector>。
16.1. <forgiving-selector-list> 和 <forgiving-relative-selector-list>
出于兼容历史的原因, 选择器列表的常规行为是:只要列表中的某个选择器未能通过解析 (比如用了新的或UA专属的选择器特性), 整个选择器列表即被视为无效。 这让使用新选择器且能兼容旧用户代理的 CSS 难以编写。
<forgiving-selector-list> 产生式 则是单独解析列表中每个选择器, 对解析失败的直接忽略, 使剩余选择器仍可被使用。
注意: 样式规则仍采用传统“不宽容”选择器列表行为。<forgiving-selector-list> 只用于 :is() 和 :where()。 虽然这对专属性有一定影响, 但只要不含伪元素, 把样式规则选择器包进 :is() 会变成宽容模式。 (伪元素在 :is() 和 :where() 中无效。)
在语法上,<forgiving-selector-list> 等价于
<any-value>?。
最终会按宽容选择器列表方式解析得到真实值。
-
按语法规则解析 input 中的 <complex-real-selector> 列表, 得到 selector list。
-
移除 selector list 中所有解析失败的项, 以及所有无效选择器, 返回代表selector list 剩余项目的 <selector-list>。 (此 selector-list 可能为空。)
<forgiving-selector-list> 中所有无效项 (无论是未知语法、上下文无效,还是用已知语法但上下文非法), 均应视为专属性为零。
注意: <forgiving-selector-list> 只用于 :is() 和 :where(),不会用于其它带选择器参数的选择器。
17. API 钩子
为方便规范使用 Selector 概念, 本节定义了可被其他规范调用的若干 API 钩子。
现在既然我们对 match 和 invalid selector 有更严格定义,
这些是否还需要?
名词协调起来比谓词简单,
而像 querySelector 返回元素顺序的细节应该更适合在 DOM 规范而不是 Selector 里定义。
17.1. 解析选择器
本节定义了如何从字符串 source 解析选择器。 返回值要么是复杂选择器列表, 要么失败。
- 将 source 作为 解析 <selector-list> 处理,结果记为 selector。 若失败, 视为无效选择器, 返回失败。
- 若 selector 由于其它原因(如包含未声明命名空间前缀等)是无效选择器, 返回失败。
- 否则, 返回 selector。
17.2. 解析相对选择器
本节定义了如何从字符串 source 解析相对选择器。 返回值要么是复杂选择器列表, 要么失败。
- 将 source 作为 解析 <relative-selector-list>,结果记为 selector。 若失败, 视为无效选择器, 返回失败。
- 若 selector为其他原因(如包含未声明命名空间前缀等)为无效选择器, 返回失败。
- 否则, 返回 selector。
17.3. 选择器与元素匹配
本节定义了如何用选择器匹配元素。
调用本算法的API必须参数 selector 和 element。
调用者可选参数:
本算法返回成功或失败。
对 selector(视为复杂选择器列表)中的每个复杂选择器: 按下述方式将复杂选择器与 element 匹配。 只要有任何复杂选择器匹配成功, 算法就返回成功;否则,返回失败。
要用复杂选择器匹配元素, 以复合选择器为单位,从右到左递归处理,过程如下:
- 若右侧的复合选择器里任一简单选择器与元素不匹配,则返回失败。
- 否则,若仅剩一个复合选择器,返回成功。
- 否则,考虑所有可能通过最右侧组合器 与此元素关联的元素。 若将右侧复合选择器和组合器移除后剩下的选择器,对其中任意这样的元素匹配成功,则返回成功;否则,返回失败。
17.4. 选择器与伪元素匹配
本节定义了如何用选择器匹配伪元素。
调用本算法的API必须参数 selector 和 pseudo-element。 可选参数同“选择器与元素匹配”。
本算法返回成功或失败。
对 selector 中每个 复杂选择器,如果:
- 复杂选择器最右侧的简单选择器 能匹配 pseudo-element,且
- 对复杂选择器剩余部分(仅移除最右侧简单选择器),以 pseudo-element 的对应元素为目标,调用“用复杂选择器匹配元素”算法,返回成功,
否则(即 selector 全部复杂选择器都不满足上面情况),返回失败。
17.5. 选择器与树匹配
本节定义了如何用选择器匹配一棵树。
调用本算法的API必须提供一个选择器, 以及一个或多个 root elements,表示要在这些子树中查找。 所有 root elements 必须有相同的树根,否则调用无效。
可选参数:
算法返回一个(可能为空的)元素列表。
- 初始 candidate elements 列表为 root elements 及其所有后代元素, 按包含 Shadow DOM 的树顺序排序,除非另行指定。
- 若提供了作用域根, 则从 candidate elements 中移除不属于任一 作用域根 的元素。
- 初始化 selector match list 为空。
- 对 candidate elements 列表中每个 element:
附录A:源文档与数据映射为元素树的指导
本节为说明性质。
DOM 所描述的元素树结构强大而实用, 但也足够宽泛,可用于建模几乎任何描述树状数据的语言 (甚至用合适的方式也能表达图结构)。
部分语言如 HTML 已有明确流程 可根据资源生成 DOM 对象。 若某语言没有, 则必须自定义此类流程, 方可令 Selectors 可在该语言的文档上应用。
最少应由文档语言定义什么映射为 DOM “element”。
节点间的一对多关系(树结构中的父子关系、图结构中的相邻节点), 应体现在“子节点”上。
元素的其他特征应映射为 DOM 中同类特性的等价内容:
- type
-
若文档语言的元素有某种“类型”概念,
用于区分不同元素组,
则应对应于 type 特性。
如果“类型”可分为基础名和“命名空间”, 后者将不同名字归为更高一级组, 则命名空间应对应 DOM 命名空间,基础名为 type。 否则元素不设命名空间,整个名字对应 type。
- id
-
若元素的某特性能在文档中全局唯一标识,
则应映射为 id 特性。
注意: HTML 只允许单 id, 这并非通用限制。 id 真正需保证的只是“不重复”; 同一元素可有多个 id。
- classes 和 attributes
- 元素有助于身份识别但在文档中不唯一的特征, 如仅是“标签”可做 class,用于说明特性的键值对可做 attribute。
- 伪类和伪元素
-
若有元素需要匹配任何伪类或拥有伪元素,
必须显式定义。
有些伪类属于“语法类”, 如:has() 和:is(), 因此应总是生效。 需在其它地方标明。 大致只要子项列表有序,结构型伪类总起作用。
- JSON 文档的“元素”分别为每个数组、对象、布尔值、字符串、数字或 null。 数组和对象元素的内容作为其子元素。
- 每个元素的类型就是它的 JS 类型名: “array”、“object”等。
- 对象的子元素 会将它们的 key 作为类。
- 数组的子元素会匹配:first-child、:nth-child()等伪类。
- 根对象会匹配:root。
- 它还额外定义了 :val() 和 :contains() 伪类, 用于匹配具有特定值的布尔值/数字/字符串元素 或包含某个子字符串的元素。
这种结构已足以让选择器对 JSON 文档实现强大而简洁的查询。
附录B:为网页兼容保留的 -webkit-
解析兼容怪癖
本附录为规范性内容。
由于遗留的 Web 兼容性约束, 期待解析 Web 文档的用户代理必须支持下列特性:
-
所有其他 伪元素,其名称以字符串 “-webkit-” 开头 (按 ASCII 不区分大小写 进行匹配) 且不是函数表示法的,必须在解析时被视为有效。 (也就是说,::-webkit-asdf 在解析时被视为有效, 但 ::-webkit-jkl() 则不被视为有效。) 若它们未被识别或支持, 则必须视为不匹配任何元素,并被归类为 未知的 -webkit- 伪元素。
未知的 -webkit- 伪元素 在序列化时 必须使用 ASCII 小写。
这个怪癖是关于什么的?
长期以来,选择器有一种行为:当遇到单个未知或无效的选择器时, 会使整个选择器列表失效(而不是仅使其中包含它的那一个复杂选择器失效)。 工作组普遍认为这属于一个遗留错误, 但现在无法修复, 因为太多样式表有意或无意地依赖此行为。
这一行为的一个方面是:使用厂商特定的选择器会在不识别它们的其他用户代理中使整个选择器失效, 并导致整条样式规则被丢弃。 过去有人刻意利用这一点——以极不推荐的方式通过使样式在其他浏览器中无效来对某些浏览器“隐藏”样式规则—— 也有人无意中遇到此问题,即为某元素设置样式并同时把这些样式应用到厂商特定的伪元素 (例如某些浏览器公开的与
input相关的伪元素), 却没有意识到这会把整条规则对其他浏览器隐藏起来。除了一般性的原因外, 源自 WebKit 的用户代理(如 Safari 或 Chrome)还存在一个与厂商前缀伪元素相关的额外怪癖, 即任何以 ::-webkit- 为前缀的选择器在解析时都被视为有效。 (这很可能是早期 CSS 特性遗留的怪癖, 当时曾有一项已放弃的特性在解析时将所有可能的伪元素视为有效, 以便将来允许作者定义自有伪元素。)
类似其它遗留怪癖(例如 [QUIRKS] 中记载的那些), 这个特定的厂商相关奇怪行为已经足够常见,以至于其他用户代理发现有网站因依赖它而出现兼容性问题, 无论是有意还是无意。 因此,鉴于该怪癖在实践中已成为正确呈现现代网页的“必要”条件, 将其明确规范并要求所有用户代理实现, 可以提高当今网页在当前与未来的用户代理中正确呈现的概率。
然而,与所有怪癖一样, 故意依赖此行为的网页会受到 CSSWG 成员和所有理性开发者的谴责与嘲讽。
附录 C:示例性的保护隐私的 :visited 限制
先前为保护用户在使用 :visited 时的隐私所做的尝试, 涉及 复杂的限制和行为, 用以“对外撒谎”该链接是否匹配 :visited 或 :link, 以减少恶意站点在仍允许 :visited 正常工作的同时, 观察用户曾访问过哪些不相关站点的可能性。 这最终是一场无法取胜的军备竞赛; 即便有这些缓解措施,仍有多种已记录的方法可以提取用户的浏览历史。
本节描述一种方法,该方法最先在 https://github.com/explainers-by-googlers/Partitioning-visited-links-history 上开发并记录,将用户的浏览历史信息进行分区, 以使 :visited 仅匹配那些站点源本身有可能观察到的导航对应的链接。 这样,:visited 可以被视为普通伪类, 无需上述那些复杂的缓解措施, 因为它不会暴露站点本身理论上无法获得的信息, 同时尽可能保留 :visited 对用户的实用性。
-
令 visited history 为一个包含三元组的 集合(有序集合), 每个元组包含三条信息:
-
每当在页面内触发一次导航(例如用户点击链接,或页面上的脚本发起导航)时, 向 visited history 添加一条记录,记录该导航的目的地 URL、 含链接或脚本的页面的 origin, 以及包含该页面的顶级站点(按 schemeful 规则)的 site(该 site 可能与前述 origin 相同)。
注意: 这允许站点看到从该站点的任意地方点击的链接的 :visited 信息。 换言之,任何以该站点为起点的
A -> B导航都会被记录。此外,还应向 visited history 添加一条记录,记录目的地的 URL、目的地的 origin, 以及目的地所在的 site。仅对来自顶级框架或与其顶级框架同源的 iframe 发起的导航执行此操作。
注意: 这允许站点看到关于其自身页面的 :visited 信息(站点本身已能观察到该信息), 无论哪个站点发起了到该页面的导航。 换言之,任何以该站点为目的地的
A -> B导航都会被记录。注意: 值得注意的是, 由用户代理 UI 直接触发的导航(例如在地址栏输入、点击书签或从其它程序将链接拖入页面)不会添加 visited history 条目。 当然,这些来源仍可能被用户代理用于其它目的(例如在地址栏输入时为用户建议 URL)。
-
在判断某个链接元素是否应匹配 :link 或 :visited 时, 仅当该链接的目的地、包含该链接的页面的 origin,以及包含该链接的顶级站点 与 visited history 中的某个三元组相匹配时,才允许其匹配 :visited。
-
若历史条目仅按起始站点的 URL 键控, 一个跟踪站点可以作为隐藏 iframe 嵌入在多个站点中, 在首次访问时触发到一个对用户唯一区分的 URL 的导航, 随后通过多个此类链接在再次访问时检测哪一个被访问过, 从而在整个网络中充当新的“第三方 cookie”来识别用户。 通过用顶级站点来键控历史条目,这类信息就无法跨站点共享。
-
若历史条目仅按顶级站点的 URL 键控, 则一个恶意 iframe(例如作为广告出现在页面中)可能观察从顶级站点发起的访问情况。 通过用链接自身的站点来键控历史条目,顶级站点的信息就无法泄露到跨源的 iframes 中。
18. 变更
18.1. 自 2022 年 11 月 11 日工作草案以来的变更
自 2022‑11‑11 工作草案 以来的主要变更:
-
移除了 :read-write 和 :has() 的高风险标记
-
添加了 :popover-open 伪类。 (Issue 8637)
-
使 :has() 和 :nth-child()/:nth-last-child() 的选择器参数不再宽容解析。 (Issue 7676)
-
将遗留的单冒号伪元素语法移入语法规则本身。 (Issue 8122)
-
将 :local-link 伪类延期到 Level 5。 (Issue 12799)
-
将 :interest-source 和 :interest-target 伪类延期到 Level 5。 (Issue 12799)
-
将 :blank 伪类延期到 Level 5。 (Issue 12799)
-
将网格结构(列)选择器延期到 Level 5。 (Issue 12799)
-
将时间维度伪类延期到 Level 5。 (Issue 12799)
18.2. 自 2022 年 5 月 7 日工作草案以来的变更
自 2022‑05‑07 工作草案 以来的主要变更:
-
添加了 :open 伪类。 (Issue 7319, Issue 11039)
-
禁止在 伪元素 中使用 :has(),除非伪元素的定义明确允许。 (Issue 7463)
-
禁止对 :has() 进行嵌套。 (Issue 7344)
-
定义了对 ::lang("") 以及未标注语言的元素的匹配规则。 (Issue 6915)
-
彻底分离了“scoped”(有作用域)和“relative”(相对)选择器的概念。 (Issue 6399)
-
同时移除了“将选择器绝对化”的定义, 直接以锚点元素来定义相对选择器的匹配行为。
-
-
撤销了对 :nth-child() 的复合选择器限制。 (Issue 3760)
-
定义了 :-webkit-autofill 的 遗留选择器别名。 (Issue 7474)
18.3. 自 2018 年 11 月 21 日工作草案以来的变更
自 2018‑11‑21 工作草案 以来的主要变更:
- 移除了 Selector 配置文件,标记 :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> 时必须有空白的提醒改为规范性文本。
18.4. 自 2018 年 2 月 2 日工作草案以来的变更
自 2018‑02‑02 工作草案 以来的主要变更:
- 将零专属性选择器命名为 :where()。 (Issue 2143)
- 将 :matches() 重命名为 :is()。 (Issue 3258)
- 重新定义 :empty 为忽略仅包含空白的节点。 (Issue 1967)
- 重新定义 :blank, 表示空的用户输入,而非空元素。 (Issue 1283)
- 改变了 :is()、:has() 与 :nth-child() 的专属性计算方式, 使其不再依赖于哪个参数选择器被匹配。 (Issue 1027)
- 移除了 :drop() 伪类(因 HTML 放弃了相关功能)。 (Issue 2257)
- 为讨论目的草拟了一个空或仅含空白的选择器(见 未决 issue)。
- 增加了属性选择器的区分大小写标志
s。 (Issue 2101) - 对 :focus-visible 提供了更多指引。
- 添加了 附录 B:为 Web 兼容保留的 -webkit- 解析怪癖,定义了 ::-webkit- 伪元素解析的怪癖。 (Issue 3051)
- 为清晰起见重写了关于允许空白位置的语法规则。(见 § 16 语法。)
18.5. 自 2013 年 5 月 2 日工作草案以来的变更
自 2013‑05‑02 工作草案 以来的重要变更包括:
- 添加了 :target-within、:focus-within、:focus-visible、:playing 与 :paused 伪类。
- 添加了一个零专属性的 :matches()-类型伪类,名称待定。
- 用 :has() 替代了主题指示符(!)特性。
- 用 :nth-child(… of selector) 和 :nth-last-child(… of selector) 替代了 :nth-match() 和 :nth-last-match() 选择器。
- 将 :active-drop-target、:valid-drop-target、 :invalid-drop-target 用 :drop() 代替。
- 为讨论起草了一个空或仅含空白的选择器(见 未决 issue)。
- 将 :user-error 重命名为 :user-invalid。 (见 讨论)
- 将 :nth-column()/:nth-last-column() 重命名为 :nth-col()/:nth-last-col(),以避免与可能的 ::column 伪类命名上的混淆。
- 更改了 :local-link 非函数形式伪类以考虑片段 URL。
- 移除了
:local-link()的函数形式和引用组合子,因缺乏兴趣。 - 使用 CSS 值定义语法重写了选择器语法。
- 将 相对选择器 从 有作用域选择器 中拆分出来,因两者为可独立使用的不同概念。
- 将 <An+B> 微语法移动到 CSS Syntax 模块。
-
新增章节:
- § 3.2 数据模型
-
§ 17 API 钩子
- 注意早期版本在该节中定义了“求值选择器”的部分(evaluating a selector),但该部分现已移除。 引用该部分的规范应改为引用用于 在树上匹配选择器 的算法。
- 移除了对 :matches() 和 :not() 中组合子限制; 参见 讨论。
- 定义了 选择器列表的专属性(specificity)。(为啥?)
- 要求在涉及星号通配的 :lang() 值周围加引号;只有恰好为 CSS 标识符的语言代码可以不加引号。
注意: 2018‑02‑01 草案误提交了未完成的工作; 2018‑02‑02 已回退该提交(并顺便修复了一些链接)。
18.6. 自 2012 年 8 月 23 日工作草案以来的变更
自 2012‑08‑23 工作草案 以来的主要变更包括:
- 新增了:placeholder-shown伪类。
- 放宽了对:matches()和:not()的部分限制。
- 定义了快速完整的选择器特性集(现称为“live”和“snapshot”)。
- 改进了specificity(优先级)的定义,以更好地处理:matches()。
- 更新了语法规则。
- 完善了<An+B> 表达式的定义。
- 新增scope-relative选择器的定义,将scope-constrained更名为scope-filtered,以避免与scope-contained混淆。
- :local-link()伪类现在会忽略末尾的斜杠。
18.7. 自 2011 年 9 月 29 日工作草案以来的变更
自 2011‑09‑29 工作草案 以来的主要变更包括:
- 按照 RFC 4647 添加了语言变体处理。
- 添加了有作用域选择器。
- 添加了 :user-error(现称为 :user-invalid)。
- 添加了 :valid-drop-target。
- 将列组合子(column combinator)从双斜线改为双竖线。
18.8. 自 Level 3 以来的新增项
自 Level 3 以来的新增内容:
- 扩展了 :not(),使其接受选择器列表。
- 添加了 :is() 与 :where() 以及 :has()。
- 添加了 :scope。
- 添加了 :any-link。
- 添加了 :target-within、:focus-within 与 :focus-visible。
- 添加了 :dir()。
- 扩展了 :lang() 以接受通配符匹配和语言代码列表。
- 扩展了 :nth-child() 以接受选择器列表。
- 并入了来自 CSS Basic User Interface Module Level 3 的输入选择器, 并重新添加了 :indeterminate。
- 添加了 :user-invalid。
- 添加了属性值匹配的区分大小写/不区分大小写标志。
19. 致谢
CSS 工作组感谢多年来为 早期 Selectors 规范 做出贡献的每一位, 正是那些规范奠定了本规范的基础。 特别地,工作组对以下在 Selectors Level 4 中做出具体贡献的人表示特别感谢: L. David Baron, Andrew Fedoniouk, Daniel Glazman, Ian Hickson, Grey Hodge, Lachlan Hunt, Anne van Kesteren, Jason Cranford Teague, Lea Verou
隐私注意事项
- :visited 伪类若用户代理未谨慎屏蔽会被脚本读取的信息, 可能泄露用户此前访问过哪些站点的信息。
- :autofill 伪类可能暴露用户是否曾与该表单交互过; 不过同样的信息也可由观察表单被填写的速度推断得出。
安全注意事项
上述的 隐私注意事项 也可被视为影响安全的因素。