B04 伪类与伪元素

2026-10-31 17:160 阅读约 10 分钟CSS

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 验证与讨论

  1. 用元素面板的 :hov 强制悬停,确认链接下划线出现。
  2. 用键盘 Tab 聚焦,确认轮廓显示;鼠标点击时不出现轮廓。
  3. 在输入框输入非法值,确认边框变红;清空后恢复。
  4. 检查 .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 讨论

参考文献

[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

0/2000

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