CSS 伪类
伪类是选择器的一种,它用于选择处于特定状态的元素,比如当它们是这一类型的第一个元素时,或者是当鼠标指针悬浮在元素上面的时候。它们表现得会像是你向你的文档的某个部分应用了一个类一样,帮你在你的标记文本中减少多余的类,让你的代码更灵活、更易于维护。
伪类就是开头为冒号的关键字。例如,:hover 就是一个伪类。
基本用法
如果我们想要让一篇文章中的第一段变大加粗,像下面这样:

我们可为此段加上一个类,然后为那个类添加 CSS:
<article>
<p class="first">
蔬菜对你有好处,所以你需要多吃大头菜、大葱、白萝卜、苋菜、番茄酱、甜瓜、红豆、大蒜。
</p>
<p>
秋葵浓汤、甜菜叶、玉米、鸡冠菜、菊苣、秋葵浓汤、葫芦。欧芹、葱、西葫芦、塌棵菜、豌豆芽、蚕豆、羽衣甘蓝、蒲公英、秋葵、裙带菜、番茄。蒲公英、黄瓜、花生、豌豆、花生、鸡冠菜、西葫芦。
</p>
</article>
.first {
font-size: 120%;
font-weight: bold;
}
不过,这在维护的时候可能会很麻烦。
问题来自几个方面:
- 要是文档的头部又加上一段的话呢?毕竟页面内容可能是变化的,这时需要把这个类挪到新加的这段上。
- 编辑 HTML 并不总是可行,也许是因为它是由一个 CMS 生成的,即我们根本拿不到内容,也无法为此加上类名。
这里,我们就可以使用:first-child伪类选择器,这将一直选中文章中的第一个子元素,我们将不再需要编辑 HTML。
所有的伪类以同样的方式实现。它们选中你的文档中处于某种状态的那部分,表现得就像是你已经向你的 HTML 加入类一样。
速查手册
好的,已按照你的要求将所有表格调整为三列:名称、作用(简述能干什么)、注意事项(只列举容易弄错、混淆或踩坑的地方)。
位置与结构(基于 DOM 层级)
通过元素在父容器中的位置编号或唯一性进行匹配。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:first-child |
选择父级下字面意义上的第一个子元素。 | 必须实打实是第一个孩子,前面不能有任何文本节点或其他标签,否则不选。 |
:last-child |
选择父级下字面意义上的最后一个子元素。 | 必须完全匹配最后一位,若后面有空格文本节点(部分场景)或标签,立即失效。 |
:nth-child |
按所有子元素的全局位置计数来选择。 | 经典坑:若父级该位置是其他标签,选择器直接失效(而不是选中下一个同类标签)。 |
:nth-of-type |
按同类型标签独立计数,选择特定位置的元素。 | 极易与 :nth-child 混淆:它只数同种标签,无视 <p>、<div> 等异类干扰。 |
:first-of-type |
选择父级下第一个特定类型的元素。 | 即使前面有其他类型的元素,它依然匹配第一个该类型(与 :first-child 完全不同)。 |
:last-of-type |
选择父级下最后一个特定类型的元素。 | 同理,它不是父级的最后一个子元素,而是该类型中的最后一个。 |
:only-child |
选择父级下唯一的一个子元素(只有一个孩子)。 | 只要父级有多个孩子(无论什么类型),就不匹配,极易与 :only-of-type 搞混。 |
:only-of-type |
选择父级下唯一的一个该类型元素。 | 父级可有其他类型孩子,只要该类型仅出现一次就匹配(与 :only-child 的核心区别)。 |
:empty |
选择完全没有任何子节点(含文本)的元素。 | 高频 Bug:标签内有换行符或空格会被视为文本节点,导致不匹配。 |
用户动作与交互(基于行为状态)
响应用户的鼠标、触摸或键盘操作。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:hover |
鼠标悬停在元素上时触发样式。 | 移动端点击后容易产生粘滞残留,需配合 @media (hover: hover) 限制,否则体验差。 |
:focus |
元素获得焦点时触发(鼠标点击或键盘 Tab)。 | 鼠标点击时也会触发,很多人误删默认 outline 会导致键盘用户无法定位,无障碍大忌。 |
:active |
元素被激活时(鼠标按下未松开)触发。 | 触摸设备上轻触通常不会持续该状态,且它必须作用在可交互元素上才稳定(如 <a>、<button>)。 |
:focus-within |
自身或任意后代获得焦点时触发。 | 容易忽略事件冒泡带来的”连锁高亮”效果,需检查是否符合预期布局。 |
:focus-visible |
仅在键盘 Tab 键聚焦时触发可见样式。 | 不兼容老旧浏览器,且它不取代 :focus,二者通常需要配合使用。 |
表单与 UI 状态(基于控件属性)
针对表单控件的值状态、可用性和选中情况。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:disabled |
匹配被禁用的表单元素。 | 被禁用的控件无法响应 :hover、:active 和 :focus,样式继承链容易混乱。 |
:checked |
匹配被选中的 radio、checkbox 或 option。 | 不适用于 <select> 标签本身,仅适用于其内部的 <option> 或输入型控件。 |
:valid / :invalid |
根据 HTML5 验证状态匹配通过/未通过。 | 大坑:没有设置 required 或 pattern 等验证属性的输入框,永远被视为 :valid。 |
:required / :optional |
基于 required 属性匹配必填/选填项。 |
仅作用于表单控件(input、select、textarea),对普通 <div> 或 <p> 无效。 |
:enabled |
匹配所有可用的表单元素(默认状态)。 | 通常单独使用无意义,且被 :disabled 的元素不会同时匹配它。 |
:in-range / :out-of-range |
基于 min/max 判断数值是否在合法区间。 |
仅对 type="number" 或 range 有效,普通文本输入框即使有 min 也无效。 |
:indeterminate |
匹配处于”半选/不确定”状态的复选框。 | 无法通过 HTML 属性设置(如 indeterminate="true" 无效),必须用 JS 的 indeterminate 属性控制。 |
逻辑组合与关系(筛选与简化)
用于组合条件、排除元素或逆向查找父级。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:not |
排除匹配括号内选择器的元素。 | 权重陷阱:括号内选择器的权重会参与总权重计算,并非固定为 0;且早期版本不支持嵌套 :not。 |
:is |
将多个选择器合并书写,简化长列表。 | 权重爆炸:权重取括号内最高的那个选择器值,容易导致后续样式难以覆盖。 |
:has |
选择包含特定子元素的父元素(父选择器)。 | 性能杀手:渲染开销极大,在大规模 DOM 或滚动列表中慎用,否则会明显卡顿。 |
:where |
与 :is 用法完全相同,用于合并选择器。 |
权重恒为 0,因此极易被任何其他类名或标签选择器意外覆盖(适合做重置,但不适合做保护性样式)。 |
:scope |
匹配当前 CSS 作用域的根节点。 | 在普通 HTML 页面中几乎用不到,主要出现在 Web Components 或 JS 的 querySelector 里,容易误用。 |
链接、锚点与语言环境(外部资源匹配)
与 URL 跳转记录、页面锚点及国际化语言设置相关。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:link |
匹配未被访问过的 <a> 链接。 |
只对具有 href 属性的 <a> 有效,无 href 的 <a> 不匹配任何链接伪类。 |
:visited |
匹配已被访问过的 <a> 链接。 |
隐私安全限制:可修改的 CSS 属性极少(仅限 color 等几个),且无法通过 JS 读取其样式。 |
:target |
匹配 URL 锚点(#hash)指向的当前元素。 | 页面加载时若 URL 无对应 #hash 则不生效;且页面内锚点跳转时会触发,需留意闪烁问题。 |
:lang |
匹配指定语言(基于 lang 属性)的元素。 |
容易用错:它支持子代码匹配(如 :lang(zh) 能匹配 zh-CN),而属性选择器 [lang="zh"] 必须完全相等。 |
:dir |
匹配从左到右(ltr)或从右到左(rtl)的书写方向。 | 无需手动添加类名,但浏览器支持度相对较新,需确认目标受众。 |
:target-within |
锚点指向自身或后代时匹配。 | 比 :target 作用范围更广,但兼容性较新,易在老旧浏览器上失效。 |
根节点与分页(文档顶层与打印)
作用于整个文档根元素或打印分页场景。
| 名称 | 作用 | 注意事项 |
|---|---|---|
:root |
匹配文档根元素(HTML 中即 <html>)。 |
优先级高于 html 标签选择器,定义 CSS 变量时推荐用 :root,但覆盖时容易因权重问题产生困惑。 |
:nth-col |
匹配表格中指定列索引的所有单元格。 | 兼容性较新,且仅在表格布局(<table>)中有效,普通 Flex/Grid 布局中使用无效。 |
:blank |
匹配仅包含空白字符(空格/换行)的元素。 | 目前仍处于提案阶段,主流浏览器支持度极低,生产环境慎用(可降级使用 :empty 替代)。 |