伪类是什么
伪类是冒号后面的一个关键字,它按元素在文档中的位置或元素的状态来选择元素。你把它附加在普通选择器后面:li:first-child、input:focus、a:hover。
链接和鼠标相关的状态伪类(:hover、:active、:visited)有专门的页面:CSS hover。
:nth-child() 与 an+b 公式
:nth-child() 接受一个数字、一个关键字或一个 an+b 公式。浏览器会依次代入 n = 0、1、2……,匹配公式得出的每一个位置(位置从 1 开始)。
| 公式 | 匹配的位置 | 含义 |
|---|---|---|
3 | 3 | 第三个子元素 |
odd 或 2n+1 | 1, 3, 5, ... | 奇数行 |
even 或 2n | 2, 4, 6, ... | 偶数行 |
3n | 3, 6, 9, ... | 每隔三个 |
n+4 | 4, 5, 6, ... | 第四个及之后 |
-n+3 | 1, 2, 3 | 前三个 |
3n+1 | 1, 4, 7, ... | 从第一个开始,每隔三个 |
输入一个公式,看看哪些项被匹配:
试试 odd、even、4、n+7、-n+5 和 2n+3。无效的公式什么都不匹配。
从末尾开始计数的版本是 :nth-last-child():li:nth-last-child(-n+2) 选择最后两项。
nth-child 与 nth-of-type 的区别
:nth-child() 统计所有兄弟元素,不管它们是什么标签,然后才检查选择器的其余部分。:nth-of-type() 只统计相同标签的兄弟元素。一旦兄弟元素混在一起,区别就显现出来了:
两端也有同样成对的伪类::first-child / :first-of-type、:last-child / :last-of-type、:only-child / :only-of-type。
:not()、:is() 与 :where()
| 伪类 | 示例 | 匹配 |
|---|---|---|
:not(X) | li:not(.done) | 不匹配 X 的元素 |
:is(X, Y) | :is(h1, h2, h3) a | 匹配列表中任意一项的元素 |
:where(X, Y) | :where(ul, ol) li | 和 :is() 相同,但优先级为零 |
:has(X) | li:has(> input:checked) | 内部包含 X 匹配项的元素 |
:not() 是日常最常用的一个,例如在各项之间加分隔线,但最后一项后面不加:
状态伪类:focus、checked、disabled、invalid
| 伪类 | 匹配 |
|---|---|
:focus | 获得键盘或鼠标焦点的元素 |
:focus-visible | 获得焦点,并且浏览器判断应该显示焦点环(通常是键盘焦点) |
:focus-within | 内部包含获得焦点元素的元素 |
:checked | 被勾选的复选框、单选按钮或被选中的 <option> |
:disabled / :enabled | 被禁用(或未被禁用)的表单控件 |
:required / :optional | 带有或不带 required 的输入框 |
:invalid / :valid | 值未通过或通过验证的输入框 |
:user-invalid | 无效,但只在用户与它交互之后才匹配 |
:placeholder-shown | 当前正在显示占位文字的输入框 |
:empty | 没有任何子元素的元素,连文字都没有 |
:target | id 与 URL 中 #fragment 相同的元素 |
点击邮箱输入框:通过 :focus-within,它的标签会变成蓝色。输入一个不是邮箱的内容,然后离开输入框::user-invalid 会让边框变成琥珀色。如果用普通的 :invalid,这个必填的空输入框在你碰它之前就已经被标成琥珀色了。
无论你怎样处理 :focus,都要保留可见的焦点样式。去掉轮廓线却不提供替代样式,使用键盘的用户就看不出自己当前在哪里。
:has(),父元素选择器
:has() 根据元素包含的内容来匹配它。它就是大家期待已久的“父元素选择器”,在当前的 Chrome、Firefox 和 Safari 中都能使用。
选择另一个套餐:整张卡片会跟随单选按钮变化,完全不需要 JavaScript。
常见错误
- 冒号前面多了空格。
li :first-child的意思是“li 内部的第一个子元素”。应写成li:first-child。 - 以为
p:nth-child(1)表示“第一个 p”。 它的意思是“第一个子元素,如果它是 p 的话”。要选第一个 p,请用:first-of-type。 - 从 0 开始计数。 位置从 1 开始:
:nth-child(0)什么都匹配不到。 - 去掉焦点轮廓线。 写
:focus { outline: none }却不提供替代样式,会破坏键盘导航。 - 混淆
:和::。:before是伪元素::before的旧写法;伪类始终只用一个冒号。
常见问题
CSS 中的伪类是什么?
伪类是冒号后面的一个关键字,它按状态或位置而不是按名称来选择元素,例如 a:hover、li:first-child 或 input:focus。它附加在普通选择器后面,大多数伪类在优先级上和类一样计算(:where() 计为零)。
CSS 中的 nth-child 是怎么工作的?
:nth-child(an+b) 匹配在兄弟元素中位置为 a×n+b 的元素,n 依次取 0、1、2 等,位置从 1 开始计数。:nth-child(3) 是第三个子元素,:nth-child(odd) 或 2n+1 是每个奇数位置的元素,:nth-child(n+4) 是第四个及之后的元素。
nth-child 和 nth-of-type 有什么区别?
:nth-child() 先统计所有兄弟元素,再检查选择器的其余部分;:nth-of-type() 只统计同一类型元素的兄弟元素。在一个 h2 后面跟着若干段落的列表中,p:nth-child(1) 什么都匹配不到,而 p:nth-of-type(1) 匹配第一个段落。
CSS 中的 :not() 怎么用?
把要排除的选择器写在括号里:li:not(.done) 匹配所有没有 done 类的列表项。它也接受一个列表,例如 input:not([type="checkbox"], [type="radio"])。
伪类和伪元素有什么区别?
伪类(一个冒号,:hover)选择处于某种状态的一个完整的现有元素。伪元素(两个冒号,::before)针对的是元素的某个部分,或者用来创建生成的内容。