第07篇:伪元素详解
第07篇:伪元素详解
如果说伪类是给已有元素添加"状态",那伪元素就是凭空"创造"元素。
::before和::after可以在不修改 HTML 的情况下,在元素前后插入内容,是 CSS 中最具创造性的特性之一。
学习目标
- 理解伪元素与伪类的本质区别
- 掌握
::before和::after的基本用法与content属性 - 学会用伪元素创建装饰性元素(引号、分隔线、图标、背景等)
- 了解
::first-line、::first-letter、::selection的排版增强能力 - 掌握伪元素的层叠上下文和定位技巧
核心知识点
一、伪元素 vs 伪类
| 伪类 (Pseudo-class) | 伪元素 (Pseudo-element) | |
|---|---|---|
| 符号 | : | :: |
| 作用 | 选中元素的状态 | 在元素前后创建虚拟内容 |
| 典型 | :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. 属性值引用
<ahref="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 3pxrgba(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:面包屑导航
实现面包屑导航,要求用伪元素在每个链接后添加>分隔符,但最后一个不添加:
<navclass="breadcrumb"><ahref="#">首页</a><ahref="#">分类</a><ahref="#">子分类</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篇:字体与排版基础,学习如何让文字看起来更专业。
