伪元素选择器
概述
伪元素选择器(Pseudo-element Selectors)用于选择元素的特定部分,例如首字母、首行、前面或后面的内容等。伪元素以双冒号 :: 开头。
语法
选择器::伪元素 {
属性: 值;
}注意: 单冒号 : 是旧语法,双冒号 :: 是新语法(推荐)。为了兼容性,浏览器通常两种语法都支持。
常用伪元素
1. ::before - 元素前面插入内容
在元素内容之前插入生成的内容。
.box::before {
content: "前缀: ";
color: red;
font-weight: bold;
}<div class="box">这是一段文字</div>
<!-- 实际显示: 前缀: 这是一段文字 -->2. ::after - 元素后面插入内容
在元素内容之后插入生成的内容。
.box::after {
content: " (后缀)";
color: blue;
}<div class="box">这是一段文字</div>
<!-- 实际显示: 这是一段文字 (后缀) -->重要: ::before 和 ::after 必须设置 content 属性,否则不会显示。
3. ::first-letter - 首字母
选择块级元素的第一个字母。
p::first-letter {
font-size: 3em;
font-weight: bold;
color: #e74c3c;
float: left;
margin-right: 5px;
}<p>这是一段文字,首字母会被放大。</p>4. ::first-line - 首行
选择块级元素的第一行。
p::first-line {
font-weight: bold;
color: #3498db;
text-transform: uppercase;
}5. ::selection - 选中的文本
选择用户选中的文本。
::selection {
background-color: #3498db;
color: white;
}注意: 只能设置有限的属性:
- color
- background-color
- cursor
- outline
- text-decoration
- text-shadow
6. ::placeholder - 占位符文本
选择输入框的占位符文本。
input::placeholder {
color: #999;
font-style: italic;
}<input type="text" placeholder="请输入用户名">7. ::marker - 列表标记
选择列表项的标记(如圆点、数字等)。
li::marker {
color: #3498db;
font-size: 1.2em;
}
ul ::marker {
content: "• ";
}
ol ::marker {
content: counter(list-item) ". ";
font-weight: bold;
}8. ::backdrop - 背景遮罩
选择模态框等全屏元素背后的背景。
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}<dialog open>
<p>这是一个模态框</p>
</dialog>权重计算
伪元素选择器的权重为 1:
p::first-letter {
/* 权重 = 1(p) + 1(::first-letter) = 2 */
font-size: 2em;
}
.box::before {
/* 权重 = 10(.box) + 1(::before) = 11 */
content: "★";
}
.container .item::after {
/* 权重 = 10(.container) + 10(.item) + 1(::after) = 21 */
content: "•";
}常见应用场景
1. 清除浮动
.clearfix::after {
content: "";
display: block;
clear: both;
}2. 装饰性图标
.link::before {
content: "→";
margin-right: 5px;
color: #3498db;
}
.download::after {
content: "⬇";
margin-left: 5px;
}<a href="#" class="link">查看详情</a>
<a href="#" class="download">下载文件</a>3. 卡片标签
.card::before {
content: "NEW";
position: absolute;
top: 0;
right: 0;
background: #e74c3c;
color: white;
padding: 5px 10px;
font-size: 12px;
border-radius: 0 10px 0 10px;
}<div class="card" style="position: relative;">
<h3>产品标题</h3>
<p>产品描述</p>
</div>4. 引用样式
blockquote::before {
content: """;
font-size: 4em;
color: #ddd;
position: absolute;
top: -20px;
left: 0;
}
blockquote::after {
content: """;
font-size: 4em;
color: #ddd;
position: absolute;
bottom: -40px;
right: 0;
}
blockquote {
position: relative;
padding: 20px;
background: #f9f9f9;
border-left: 4px solid #3498db;
}5. 分隔线
.separator::after {
content: "";
display: block;
width: 100%;
height: 1px;
background: #eee;
margin: 20px 0;
}6. 工具提示
.tooltip {
position: relative;
}
.tooltip::before {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
}
.tooltip:hover::before {
opacity: 1;
}<span class="tooltip" data-tooltip="这是一个提示信息">悬停查看提示</span>7. 加载动画
.loader::after {
content: "";
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #3498db;
border-top-color: transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}8. 渐变边框
.gradient-border {
position: relative;
background: white;
z-index: 1;
}
.gradient-border::before {
content: "";
position: absolute;
top: -3px;
left: -3px;
right: -3px;
bottom: -3px;
background: linear-gradient(45deg, #3498db, #e74c3c, #f39c12);
z-index: -1;
border-radius: 5px;
}9. 文字阴影效果
.text-shadow::after {
content: attr(data-text);
position: absolute;
left: 2px;
top: 2px;
color: rgba(0,0,0,0.3);
z-index: -1;
}
.text-shadow {
position: relative;
}<div class="text-shadow" data-text="文字阴影">文字阴影</div>10. 图片遮罩
.image-overlay {
position: relative;
overflow: hidden;
}
.image-overlay::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
opacity: 0;
transition: opacity 0.3s ease;
}
.image-overlay:hover::after {
opacity: 1;
}实战案例
案例1: 自定义复选框
/* 隐藏原复选框 */
input[type="checkbox"] {
display: none;
}
/* 自定义复选框 */
input[type="checkbox"] + label {
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #ccc;
border-radius: 4px;
cursor: pointer;
position: relative;
}
/* 选中状态 */
input[type="checkbox"]:checked + label {
background-color: #3498db;
border-color: #3498db;
}
/* 选中图标 */
input[type="checkbox"]:checked + label::after {
content: "✓";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 14px;
}案例2: 新闻卡片
.news-card {
position: relative;
padding: 20px;
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
/* 分类标签 */
.news-card::before {
content: attr(data-category);
position: absolute;
top: 20px;
right: 20px;
background: #3498db;
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
}
/* 分隔线 */
.news-card::after {
content: "";
display: block;
width: 60px;
height: 3px;
background: #3498db;
margin: 15px 0;
}<div class="news-card" data-category="科技">
<h3>新闻标题</h3>
<p>新闻内容...</p>
</div>案例3: 价格标签
.price-tag {
position: relative;
display: inline-block;
padding: 10px 20px;
background: #f39c12;
color: white;
border-radius: 5px;
}
/* 角标 */
.price-tag::before {
content: "";
position: absolute;
top: 0;
right: 0;
border-width: 0 15px 15px 0;
border-style: solid;
border-color: #fff transparent #e67e22 transparent;
}
.price-tag::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
border-width: 15px 15px 0 0;
border-style: solid;
border-color: #e67e22 transparent transparent transparent;
}案例4: 导航菜单
.nav-item {
position: relative;
padding: 10px 20px;
cursor: pointer;
}
/* 悬停下划线 */
.nav-item::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: #3498db;
transition: width 0.3s ease;
}
.nav-item:hover::after {
width: 100%;
}案例5: 按钮样式
.btn {
position: relative;
padding: 12px 30px;
background: #3498db;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
overflow: hidden;
}
/* 悬停效果 */
.btn::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
transition: left 0.5s ease;
}
.btn:hover::before {
left: 100%;
}
/* 点击效果 */
.btn:active {
transform: scale(0.98);
}案例6: 评论系统
.comment {
position: relative;
padding: 20px;
background: #f9f9f9;
border-radius: 10px;
margin-bottom: 20px;
}
/* 评论箭头 */
.comment::before {
content: "";
position: absolute;
top: 20px;
left: -10px;
border-width: 10px 10px 10px 0;
border-style: solid;
border-color: transparent #f9f9f9 transparent transparent;
}
/* 用户头像 */
.comment::after {
content: attr(data-avatar);
position: absolute;
top: 20px;
left: -50px;
width: 40px;
height: 40px;
background: #3498db;
border-radius: 50%;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}<div class="comment" data-avatar="李">
<h4>李明</h4>
<p>这是一条评论内容。</p>
</div>案例7: 时间轴
.timeline-item {
position: relative;
padding-left: 40px;
margin-bottom: 30px;
}
/* 时间点 */
.timeline-item::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
background: #3498db;
border-radius: 50%;
border: 4px solid white;
box-shadow: 0 0 0 2px #3498db;
}
/* 时间线 */
.timeline-item::after {
content: "";
position: absolute;
left: 9px;
top: 20px;
bottom: -30px;
width: 2px;
background: #ddd;
}
.timeline-item:last-child::after {
display: none;
}案例8: 标签页
.tab-content {
display: none;
}
.tab-content:target {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}<a href="#tab1">标签1</a>
<a href="#tab2">标签2</a>
<a href="#tab3">标签3</a>
<div id="tab1" class="tab-content">内容1</div>
<div id="tab2" class="tab-content">内容2</div>
<div id="tab3" class="tab-content">内容3</div>注意事项
- content 属性:
::before和::after必须设置content属性 - 只能设置一个: 每个选择器只能使用一个伪元素
- 不可选中: 伪元素生成的内容不能被用户选择
- 有限属性: 某些伪元素(如
::selection)只能设置有限属性 - 性能考虑: 过多的伪元素可能影响性能
- 兼容性: 某些伪元素在旧浏览器中不支持
伪元素与伪类的区别
| 特性 | 伪元素 | 伪类 |
|---|---|---|
| 符号 | 双冒号 :: | 单冒号 : |
| 选择内容 | 元素的特定部分 | 元素的状态 |
| 示例 | ::before, ::after | :hover, :focus |
| 数量 | 每个元素最多两个 | 可以多个 |
| 权重 | 1 | 10 |
最佳实践
- content 属性: 使用
::before和::after时必须设置 - 语义化: 不要用伪元素添加重要内容(搜索引擎无法索引)
- 性能优化: 避免过度使用伪元素
- 渐进增强: 为不支持伪元素的浏览器提供回退
- 代码注释: 复杂伪元素添加注释说明
- 可访问性: 考虑屏幕阅读器等辅助技术
- 动画效果: 合理使用伪元素实现动画效果
- 装饰用途: 主要用于装饰,避免用于核心内容
总结
伪元素选择器是 CSS 中强大的功能,能够为元素添加装饰性内容、选择特定部分。掌握各种伪元素的使用方法,可以帮助我们创建更丰富的视觉效果,减少 HTML 的复杂度。在实际开发中,要合理使用伪元素,确保代码的可维护性和性能。