第07篇:伪元素详解
如果说伪类是给已有元素添加"状态",那伪元素就是凭空"创造"元素。::before 和 ::after 可以在不修改 HTML 的情况下,在元素前后插入内容,是 CSS 中最具创造性的特性之一。
学习目标
- 理解伪元素与伪类的本质区别
- 掌握 ::before 和 ::after 的基本用法与 content 属性
- 学会用伪元素创建装饰性元素(引号、分隔线、图标、背景等)
- 了解 ::first-line、::first-letter、::selection 的排版增强能力
- 掌握伪元素的层叠上下文和定位技巧
核心知识点
一、伪元素 vs 伪类
| 符号 | : | :: |
| 作用 | 选中元素的状态 | 在元素前后创建虚拟内容 |
| 典型 | :hover、:nth-child() | ::before、::after |
| 数量 | 不影响 DOM 元素数量 | 每个元素可创建 2 个伪元素 |
💡 CSS2 中伪元素也用单冒号 :before,CSS3 规范改为 ::before 以区分。现代浏览器两种写法都支持,但推荐使用双冒号。
二、::before 与 ::after
基本语法
/* 在元素内容前面插入 */
.element::before {
content: "前缀";
color: #999;
}
/* 在元素内容后面插入 */
.element::after {
content: "后缀";
color: #999;
}
关键点:
- content 属性必须存在,即使值为空字符串 content: ""
- 伪元素默认是行内元素(display: inline)
- 每个真实元素最多有 2 个伪元素(一个 ::before,一个 ::after)
创建一个视觉元素
/* 用空 content + 样式创建纯视觉元素 */
.divider::before {
content: "";
display: block;
width: 100%;
height: 1px;
background: linear-gradient(90deg, transparent, #ddd, transparent);
}
三、content 属性详解
content 是伪元素的灵魂,它决定了伪元素"显示什么"。
1. 纯文本
.price::before {
content: "¥";
font-size: 0.8em;
}
.tag::after {
content: " HOT";
color: #e74c3c;
font-size: 0.7em;
vertical-align: super;
}
2. 属性值引用
<a href="https://example.com" data-tooltip="点击查看详情">链接</a>
/* 显示元素的属性值 */
a[href^="http"]::after {
content: " (" attr(href) ")"; /* 显示链接地址 */
color: #999;
font-size: 0.85em;
}
/* 用 data 属性实现工具提示 */
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 14px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip:hover::after {
opacity: 1;
}
3. Unicode 字符和图标
/* 使用 Unicode 字符 */
.external-link::after {
content: "\\2197"; /* ↗ 箭头 */
margin-left: 4px;
}
.success::before {
content: "\\2713"; /* ✓ 对勾 */
color: #2ecc71;
margin-right: 6px;
}
/* 使用 emoji */
.warning::before {
content: "\\26A0\\FE0F"; /* ⚠️ 警告 */
margin-right: 6px;
}
4. 计数器
/* 自动编号 */
ol.chapter {
counter-reset: chapter; /* 初始化计数器 */
}
ol.chapter li::before {
counter-increment: chapter; /* 计数器 +1 */
content: "第 " counter(chapter) " 章:";
font-weight: bold;
color: #4a90d9;
}
/* 多级嵌套计数器 */
ol.nested {
counter-reset: item;
}
ol.nested li::before {
counter-increment: item;
content: counters(item, ".") " "; /* 1.1, 1.2, 2.1… */
color: #666;
}
5. 空 content(纯视觉装饰)
/* 清浮动 */
.clearfix::after {
content: "";
display: table;
clear: both;
}
/* 背景装饰 */
.card::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #667eea, #764ba2);
}
四、伪元素实战应用
1. 引号装饰
.quote {
position: relative;
padding: 20px 40px;
font-style: italic;
color: #555;
}
/* 大引号装饰 */
.quote::before {
content: "\\201C"; /* 左双引号 " */
position: absolute;
top: -10px;
left: 10px;
font-size: 60px;
color: #ddd;
font-family: Georgia, serif;
line-height: 1;
}
.quote::after {
content: "\\201D"; /* 右双引号 " */
position: absolute;
bottom: -30px;
right: 10px;
font-size: 60px;
color: #ddd;
font-family: Georgia, serif;
line-height: 1;
}
2. 带图标的列表
.feature-list {
list-style: none;
padding: 0;
}
.feature-list li {
padding: 10px 0 10px 30px;
position: relative;
}
.feature-list li::before {
content: "\\2713"; /* ✓ */
position: absolute;
left: 0;
color: #2ecc71;
font-weight: bold;
}
/* 不同类型的图标 */
.feature-list li.warning::before {
content: "\\26A0"; /* ⚠ */
color: #ffc107;
}
.feature-list li.error::before {
content: "\\2717"; /* ✗ */
color: #e74c3c;
}
3. 工具提示(Tooltip)
.tooltip {
position: relative;
cursor: help;
border-bottom: 1px dashed #999;
}
/* 提示文字 */
.tooltip::after {
content: attr(data-tip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%) translateY(-8px);
background: #333;
color: white;
padding: 8px 14px;
border-radius: 6px;
font-size: 14px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
/* 小三角箭头 */
.tooltip::before {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%) translateY(-2px);
border: 6px solid transparent;
border-top-color: #333;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
/* 悬停时显示 */
.tooltip:hover::before,
.tooltip:hover::after {
opacity: 1;
visibility: visible;
}
4. 图片遮罩效果
.image-overlay {
position: relative;
display: inline-block;
}
.image-overlay img {
display: block;
}
/* 渐变遮罩 */
.image-overlay::after {
content: "";
position: absolute;
inset: 0; /* 等价于 top:0; right:0; bottom:0; left:0 */
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent 50%);
pointer-events: none; /* 让鼠标事件穿透到图片 */
}
/* 遮罩上的文字 */
.image-overlay .caption {
position: absolute;
bottom: 16px;
left: 16px;
right: 16px;
color: white;
z-index: 1;
}
5. 自定义复选框(纯 CSS)
/* 隐藏原生复选框 */
.custom-checkbox input[type="checkbox"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
/* 自定义方框 */
.custom-checkbox label {
position: relative;
padding-left: 32px;
cursor: pointer;
line-height: 24px;
display: inline-block;
}
.custom-checkbox label::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
border: 2px solid #ddd;
border-radius: 4px;
transition: all 0.2s;
}
/* 选中状态:背景变蓝 + 对勾 */
.custom-checkbox input:checked + label::before {
background: #4a90d9;
border-color: #4a90d9;
}
.custom-checkbox input:checked + label::after {
content: "";
position: absolute;
left: 7px;
top: 3px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
/* 聚焦状态 */
.custom-checkbox input:focus + label::before {
box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.3);
}
五、排版伪元素
::first-line — 首行样式
/* 文章段落的首行加大、加粗 */
article p::first-line {
font-weight: bold;
font-size: 1.1em;
line-height: 1.4;
}
/* 注意:只能用于块级元素,且只能设置以下属性:
font、color、background、word-spacing、letter-spacing、
text-decoration、text-transform、line-height
*/
::first-letter — 首字下沉
/* 杂志风格的首字下沉 */
.article-body::first-letter {
float: left;
font-size: 3.5em;
line-height: 1;
padding-right: 8px;
color: #4a90d9;
font-family: Georgia, serif;
}
::selection — 选中文本的样式
/* 自定义文字选中的高亮色 */
::selection {
background: #4a90d9;
color: white;
}
/* 特定元素的选中文本 */
.dark-section ::selection {
background: #ffc107;
color: #1a1a2e;
}
/* 注意:::selection 只能设置 color、background-color、text-shadow 等少数属性 */
::placeholder — 占位符样式
input::placeholder {
color: #bbb;
font-style: italic;
}
input:focus::placeholder {
color: #ddd; /* 获得焦点时占位符变淡 */
}
六、伪元素的定位与层叠
伪元素的包含块
伪元素的包含块就是其依附的元素。
.card {
position: relative; /* 给伪元素创建定位上下文 */
}
/* 角标 */
.card::before {
content: "NEW";
position: absolute;
top: -10px;
right: -10px;
background: #e74c3c;
color: white;
padding: 4px 12px;
font-size: 12px;
border-radius: 4px;
}
伪元素的层叠顺序
默认情况下,::before 在内容下方,::after 在内容上方。
.layer-demo {
position: relative;
}
/* z-index 控制层叠 */
.layer-demo::before {
content: "";
position: absolute;
z-index: -1; /* 放到最底层 */
background: #e3f2fd;
}
.layer-demo::after {
content: "";
position: absolute;
z-index: 1; /* 放到最上层 */
background: rgba(0,0,0,0.5);
}
动手练习
练习 1:创建步骤指示器
用伪元素创建一个横向的步骤指示器(Stepper),要求:
- 每个步骤之间有连接线(用 ::before 或 ::after)
- 已完成步骤为蓝色,当前步骤为橙色,未开始为灰色
- 步骤编号用计数器自动生成
练习 2:面包屑导航
实现面包屑导航,要求用伪元素在每个链接后添加 > 分隔符,但最后一个不添加:
<nav class="breadcrumb">
<a href="#">首页</a>
<a href="#">分类</a>
<a href="#">子分类</a>
<span>当前页面</span>
</nav>
练习 3:加载动画
用 ::before 和 ::after 创建一个纯 CSS 的加载动画:
- 两个伪元素都是圆形,不同大小
- 一个顺时针旋转,一个逆时针旋转
- 使用 border 的透明部分实现圆弧效果
常见误区 ⚠️
| “伪元素是真实 DOM 元素” | 伪元素不在 DOM 树中,无法用 JS 直接操作(但可以通过 CSS 变量间接控制) |
| “content 可以省略” | content 必须存在,即使是空字符串。不写 content 伪元素不会显示 |
| “伪元素可以添加在所有元素上” | 大多数元素支持,但替换元素(如 img、input、iframe)的伪元素支持有限或不稳定 |
| “::before 在内容前面,::after 在内容后面,所以 before 的 z-index 更低” | 默认 ::before 确实在内容下层、::after 在上层,但可以用 z-index 改变 |
| “伪元素可以无限嵌套” | 每个元素最多只有 ::before 和 ::after 两个伪元素,伪元素自身不能再有伪元素 |
| “content: url('image.png') 和 background-image 一样” | content: url() 插入的图片无法控制尺寸,且会被拉伸失真。装饰性图片建议用 background-image |
| “::selection 可以设置任意样式” | 只能设置 color、background-color、text-shadow 等少数属性 |
| “伪元素的内容可以被选中复制” | ::before/::after 生成的文本可以被选中复制,但计数器生成的数字不行 |
速查卡片 📋
常用伪元素
| ::before | 元素内容之前插入 |
| ::after | 元素内容之后插入 |
| ::first-line | 首行样式 |
| ::first-letter | 首字样式 |
| ::selection | 选中文本样式 |
| ::placeholder | 占位符样式 |
content 取值类型
| 文本 | content: "前缀" |
| Unicode | content: "\\2713" |
| 属性 | content: attr(data-tip) |
| 计数器 | content: counter(item) |
| 空 | content: "" |
| URL(不推荐) | content: url(icon.png) |
伪元素必备三件套
.element::before {
content: ""; /* 必须 */
display: block; /* 视情况 */
position: absolute; /* 视情况 */
}
扩展阅读
- MDN: 伪元素
- MDN: ::before
- MDN: ::after
- CSS-Tricks: A Whole Bunch of Amazing Stuff Pseudo Elements Can Do(英文)
- CSS 计数器详解
📌 配套代码:
- CODE/07/pseudo-elements-decoration.html — 装饰性伪元素实战
- CODE/07/pseudo-elements-tooltip.html — 工具提示完整示例
🎉 下一步:进入 第08篇:字体与排版基础,学习如何让文字看起来更专业。




