B04 伪类与伪元素
B04 伪类与伪元素
摘要:伪类描述元素的状态与位置,伪元素生成元素内部的虚拟部件。用它们可以把「悬停变色」「表单错误态」「每行最后一个去边框」这类规则写进 CSS,而不必加类名或额外标签。边界在于:伪类依赖真实状态,伪元素生成的内容不进可访问性树。
关键词:伪类,伪元素,结构选择器,状态,content
所属:frontend/css / B-进阶 | 上一篇:B03-定位与层叠上下文 | 下一篇:B05-变换过渡与动画
1 引言
状态样式有三条实现路径:加类名、用伪类、靠脚本。前者污染 HTML,后者增加运行时成本,伪类由浏览器维护状态,是最省的一层。
本文给出状态与结构两类伪类,以及伪元素的使用边界。范围见表 1-1。
| 项 | 本文覆盖 | 本文不覆盖 |
|---|---|---|
| 状态 | :hover、:focus-visible、:active、:disabled、:checked、:invalid |
完整表单状态(C02) |
| 结构 | :first-child、:nth-child()、:not()、:is()、:where() |
选择器性能分析 |
| 伪元素 | ::before、::after、::marker、::selection、::placeholder |
表格与列表的完整伪元素清单 |
2 预备知识
| 项 | 要求 | 核对方式 |
|---|---|---|
| 环境 | 本地服务器可用 | 浏览器能打开 localhost |
| 文件 | css-practice/pseudo.html |
编码 UTF-8 |
| 浏览器 | Chrome 130+,:hov 强制状态可用 |
元素面板可模拟悬停 |
| 前置 | A02 | 会算权重 |
3 原理与实现
3.1 伪类与伪元素的分工
两者作用对象不同,混用会导致样式不生效,如图 3-1 所示。
flowchart LR
A["选择器"] --> B["伪类 :xxx<br/>选中处于某状态的元素"]
A --> C["伪元素 ::xxx<br/>生成元素内部的部件"]
B --> B1["hover / focus / nth-child"]
C --> C1["before / after / marker"]
C1 --> C2["需要 content 才渲染"]
图 3-1 伪类与伪元素的区别
图上可见:伪元素没有真实 DOM 节点,写入的文字不会被朗读软件读取,也不可被选中复制。
3.2 常用写法
/* 运行环境:Chrome 130+;css-practice/pseudo.css */
.link:hover { text-decoration: underline; }
.link:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }
input:invalid { border-color: #b91c1c; }
input:disabled { background: #f1f5f9; color: #94a3b8; }
.list > li:nth-child(odd) { background: #f8fafc; }
.list > li:not(:last-child) { border-block-end: 1px solid #e2e8f0; }
.card::before {
content: "";
position: absolute;
inset-block-start: 0;
inset-inline-start: 0;
width: 0.25rem;
height: 100%;
background: #1d4ed8;
}
.tag::after { content: " ›"; color: #94a3b8; }
::selection { background: #dbeafe; }
::placeholder { color: #94a3b8; }
常用伪类与伪元素见表 3-1。
| 名称 | 类型 | 作用 | 常见误用 |
|---|---|---|---|
:hover |
伪类 | 指针悬停 | 移动端依赖悬停 |
:focus-visible |
伪类 | 键盘聚焦时显示轮廓 | 用 :focus 导致鼠标点击也画框 |
:active |
伪类 | 按下瞬间 | 与 :focus 混用 |
:disabled |
伪类 | 禁用控件 | 只改颜色不禁用 |
:checked |
伪类 | 选中状态 | 用于非表单元素 |
:invalid |
伪类 | 值不满足约束 | 页面初始就标红(未加 :user-invalid) |
:nth-child(n) |
结构 | 按位置选 | 与 :nth-of-type 混用 |
:not() |
结构 | 排除 | 嵌套过深导致难读 |
:is() / :where() |
结构 | 简化组合权重 | :where() 权重为 0,易被覆盖 |
::before/::after |
伪元素 | 生成装饰或图标 | 缺少 content 不渲染 |
::marker |
伪元素 | 列表标记 | 需要自定义动效时受限 |
三条规则:装饰性内容用伪元素,有语义的文字必须写在 HTML 里;:focus 一律替换为 :focus-visible,避免鼠标点击出现轮廓;:where() 用于低权重的基础样式,方便后续覆盖。
4 验证与讨论
- 用元素面板的
:hov强制悬停,确认链接下划线出现。 - 用键盘
Tab聚焦,确认轮廓显示;鼠标点击时不出现轮廓。 - 在输入框输入非法值,确认边框变红;清空后恢复。
- 检查
.card::before的装饰条是否影响文字排版,确认未遮挡内容。
| 检查项 | 预期结果 | 说明 |
|---|---|---|
| 悬停态 | 下划线出现 | :hover |
| 键盘焦点 | 有轮廓;鼠标点击无 | :focus-visible |
| 错误态 | 边框变红,无额外类名 | :invalid |
| 伪元素 | 装饰条显示但不遮挡内容 | 定位与层级 |
| 复制文字 | 伪元素内容不被复制 | 无真实节点 |
讨论与局限。 :invalid 在页面初始就会命中空字段,用户尚未输入就看到红框;现代浏览器提供 :user-invalid 区分「已交互且无效」。另伪元素无法绑定事件,交互行为仍要靠真实元素。
5 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 伪元素不显示 | 缺少 content |
补 content: "" |
| 伪元素盖住文字 | 未设 z-index 或未留内边距 |
调整层级或增加 padding |
| 表单初始就标红 | :invalid 默认命中空值 |
改用 :user-invalid |
| 悬停样式在手机上卡住 | 触摸设备无悬停概念 | 关键信息不依赖悬停 |
:nth-child 命中错位 |
混入了其它标签元素 | 改用 :nth-of-type 或限定子元素类型 |
6 结论
| 序号 | 结论 | 依据 |
|---|---|---|
| 1 | 伪类管状态,伪元素管部件 | 图 3-1 |
| 2 | 键盘焦点用 :focus-visible |
表 3-1 |
| 3 | 装饰用伪元素,语义用真实元素 | 表 3-1 |
| 4 | 表单错误态优先用 :user-invalid |
讨论 |
- 上一篇:B03-定位与层叠上下文
- 下一篇:B05-变换过渡与动画
- 返回:B00-总结 | 科目 README
参考文献
[1] MDN Web Docs · 伪类与伪元素,https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-classes(访问于 2026-10-31)
[2] Selectors Level 4,W3C,https://www.w3.org/TR/selectors-4/(访问于 2026-10-31)

评论 0
还没有评论,快来抢沙发吧~