前端必备:CSS 伪类与伪元素解析
本文内容基于 AI 生成结果整理,可能包含不准确信息,仅供参考使用。
作为前端开发者,伪类 ( Pseudo-classes ) 和伪元素 ( Pseudo-elements ) 是我们每天都会用到的 CSS 特性,但许多人对它们的区别理解模糊。本文将用最直观的方式揭示它们的本质差异。
概念速记卡
特性 | 伪类 | 伪元素 |
---|---|---|
代表 | :hover , :first-child |
::before , ::first-line |
作用 | 选择元素的特定状态 | 创建元素的虚拟子元素 |
DOM | 不创建新节点 | 创建不在 DOM 中的虚拟节点 |
内容 | 不能使用 content 属性 | 必须配合 content 属性使用 |
浏览器支持 | 所有浏览器 | CSS3+(需注意双冒号语法) |
优先级 | 类选择器级别 | 元素选择器级别 |
本质区别图解

7 大核心区别详解
1. 创建机制不同
- 伪类只是"选择"已存在的元素
- 伪元素会"创建"新的虚拟元素
css
/* 伪类:选择被悬停的按钮 */
button:hover {
background: blue; /* 修改现有元素样式 */
}
/* 伪元素:在按钮前创建新内容 */
button::before {
content: "→"; /* 必须的content属性 */
color: white;
}
2. DOM 表现差异
- 伪类不会出现在 DOM 检查器中
- 伪元素会显示在浏览器的 DOM 面板中(带双冒号标记)
3. 内容生成能力
css
/* 伪类无法生成内容 - 以下代码无效! */
a:hover {
content: "点击我"; /* 无效声明 */
}
/* 伪元素必须定义content才有意义 */
.tooltip::after {
content: attr(data-tip); /* 有效的内容生成 */
}
4. 层级关系不同
伪元素会创建新的层级上下文:
css
<style>
.box {
position: relative;
}
.box::before {
content: "";
position: absolute; /* 可以独立定位 */
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
</style>
<div class="box">内容</div>
实际渲染顺序:::before → 元素内容 → ::after → :hover
5. 样式继承规则
- 伪类 :继承所选元素的所有可继承样式
- 伪元素 :默认不继承父元素的某些样式(需显式设置)
css
div {
font-size: 20px;
color: red;
}
div:hover {
/* 自动继承div的font-size和color */
}
div::before {
/* 需要手动设置继承 */
content: "";
font-size: inherit;
color: inherit;
}
6. JavaScript 可操作性
- 伪类 :可通过 JS 触发状态变化如 element.classList.add(‘hover’)
- 伪元素 :无法通过 JS 直接操作只能通过修改 CSSRule 间接影响
7. 浏览器渲染性能
操作 | 伪类开销 | 伪元素开销 |
---|---|---|
首次渲染 | 低 | 中 |
动态状态变化 | 极低 | 高 |
动画性能 | 优秀 | 较差 |
性能建议
高频交互效果优先使用伪类实现
组合使用示范
两者可以组合使用实现复杂效果:
css
/* 当卡片悬停时,在卡片后添加箭头图标 */
.card:hover::after {
content: "→";
position: absolute;
right: 10px;
}
经典应用场景对比
伪类典型用例
- 交互反馈(:hover, :active)
- 表单状态(:checked, :disabled)
- 结构选择(:nth-child(), :first-of-type)
- 链接状态(:visited, :link)
伪元素典型用例
- 装饰性内容(::before, ::after)
- 文本特效(::first-letter, ::selection)
- 清除浮动(.clearfix::after)
- 自定义列表编号(counter()函数)
实战代码演示
案例 1:表格行交互
css
/* 伪类控制行悬停效果 */
tr:hover {
background: #f5f5f5;
}
/* 伪元素添加行首标记 */
tr::before {
content: "";
display: inline-block;
width: 5px;
background: blue;
}
案例 2:自定义复选框
css
/* +(相邻兄弟选择器) */
.checkbox:checked + label::before {
content: "✓";
color: green;
}
.checkbox:disabled + label::after {
content: "(不可用)";
color: gray;
}
常见误区解答
Q1. 为什么我的::before 不显示?
答:检查是否设置了 content 属性,即使是空字符串 content: ““也必须写
Q2. 单冒号和双冒号的区别?
答:
CSS2 时代伪元素用单冒号(:before)
CSS3 规范改为双冒号(::before)
浏览器对两种写法都支持,但建议用双冒号
Q3. 伪元素可以绑定事件吗?
答:不能!伪元素不是真实 DOM 元素,无法通过 JavaScript 添加事件监听
性能优化建议
- 避免过度使用伪元素:每个伪元素都会创建额外的渲染层
- 复杂动画优先用伪类:伪元素的动画性能开销更大
- 动态内容用 DOM 实现:伪元素的 content 无法实时更新
总结选择器优先级
当伪类和伪元素组合使用时,优先级计算规则:
- !important > 行内样式 > ID 选择器 >
- 类选择器/属性选择器/伪类 >
- 元素选择器/伪元素 >
- 通配符选择器