跟着 MDN 学CSS day_6:(伪类和伪元素详解)

在CSS选择器的学习旅程中,我们已经掌握了基础选择器、属性选择器等众多知识点。今天要介绍的伪类和伪元素,是CSS体系中极为重要但又常常让初学者感到困惑的概念。它们之所以被称为"伪",是因为它们并不直接对应HTML文档中的真实元素,而是基于元素的状态、位置或特定部分来进行选择。掌握这些选择器,可以让你的CSS代码更加灵活、优雅,同时减少不必要的类名污染。


一、什么是伪类

伪类用于选择处于特定状态 的元素。这里的"状态"可以是多种多样的:元素是其父元素的第一个子元素、鼠标正悬停在元素上方、输入框的内容不合法、链接已经被访问过等等。伪类以单冒号开头,后面紧跟伪类名称。

为什么需要伪类?

想象一个场景:你需要为文章容器内的第一个段落设置特殊的样式。传统做法是为这个段落添加一个类名,然后编写针对这个类的CSS规则。但这样做有两个问题:

  1. 你的HTML会多出一个仅为样式服务的类名
  2. 如果后续在文章开头又插入了一个新段落,你需要手动调整类名的位置

伪类完美解决了这些问题------它们就像是动态添加的类,无需修改HTML结构。


二、结构性伪类

结构性伪类允许你根据元素在DOM树中的位置 来进行选择。最常用的包括 :first-child:last-child:nth-child 等。

示例场景

我们希望文章容器中的第一个段落具有更大的字号和加粗效果。

HTML结构
html 复制代码
<article class="post">
  <p>这是文章的第一段内容。作为开篇段落,我们希望它能够更加醒目,吸引读者的注意力。</p>
  <p>这是第二段。它的样式应该保持常规,不需要特殊处理。</p>
  <p>这是第三段。同样使用默认样式即可。</p>
</article>
CSS样式
css 复制代码
.post p:first-child {
  font-size: 120%;
  font-weight: bold;
  color: #2c3e50;
}

💡 解析 :这段CSS选择器的含义是------选择 class="post" 的元素内部的所有 p 元素,但仅限于那些是其父元素的第一个子元素p 元素。

运行这段代码后,你会发现只有第一个段落应用了大号和加粗的样式。如果你在 article 内部的最前面插入一个新段落,这个新段落会自动成为 :first-child,样式会自动应用到它身上,无需修改任何 JavaScript 或 HTML 代码


三、用户行为伪类

用户行为伪类也被称为动态伪类 ,它们只有在用户与文档进行交互时才会生效。最常见的有 :hover:focus

  • :hover ------ 在用户将鼠标指针移动到元素上方时触发
  • :focus ------ 在元素获得键盘焦点时触发

这些伪类对于提升用户体验至关重要,尤其是在链接、按钮和表单元素上。

示例场景

为一个链接设置不同的状态样式。

HTML结构
html 复制代码
<nav>
  <a href="#" class="nav-link">首页</a>
  <a href="#" class="nav-link">关于我们</a>
  <a href="#" class="nav-link">服务项目</a>
  <a href="#" class="nav-link">联系我们</a>
</nav>
CSS样式
css 复制代码
.nav-link {
  display: inline-block;
  padding: 8px 16px;
  text-decoration: none;
  border-radius: 4px;
  transition: all 0.3s ease;
}

.nav-link:link,
.nav-link:visited {
  background-color: #3498db;
  color: white;
}

.nav-link:hover {
  background-color: #2980b9;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.nav-link:focus {
  outline: 2px solid #f1c40f;
  outline-offset: 2px;
}
状态说明
伪类 作用
:link 未访问的链接
:visited 已访问的链接
:hover 鼠标悬停时的视觉反馈
:focus 键盘导航时的焦点指示

⚠️ 可访问性提示:focus 伪类对于网站的可访问性非常重要。许多用户依赖键盘而非鼠标来浏览网页,如果没有明确的焦点指示器,这些用户将无法知道当前页面上哪个元素可以交互。

注意到我们使用了 transition 属性,这让状态切换时产生平滑的过渡效果,而不是生硬的跳变。


四、伪元素是什么

伪元素与伪类有着本质的区别 。如果说伪类像是在现有元素上动态添加一个类,那么伪元素就像是向DOM中插入了一个全新的、不可见的元素。伪元素允许你样式化元素中并不独立存在的部分,比如一段文字的第一行、第一个字母,或者在元素内容的前后插入额外内容。

伪元素使用双冒号 开头,这是CSS3引入的规范,用以区分单冒号的伪类。不过为了向后兼容,浏览器也支持使用单冒号书写早期的伪元素,如 :before:after 等。


五、::first-line 伪元素

::first-line 选择器会选中元素的第一行文本 ,无论这一行在浏览器视口中具体包含了哪些单词和字符。这个选择器非常智能------当浏览器窗口大小改变,第一行的内容发生变化时,样式会自动重新应用,无需任何额外工作。

示例场景

为文章段落的第一行设置特殊的样式效果。

HTML结构
html 复制代码
<article class="content">
  <p>昔者,共工与颛顼争为帝,怒而触不周之山,天柱折,地维绝。天倾西北,故日月星辰移焉;地不满东南,故水潦尘埃归焉。</p>
  <p>女娲炼五色石以补苍天,断鳌足以立四极,杀黑龙以济冀州,积芦灰以止淫水。苍天补,四极正,淫水涸,冀州平。</p>
</article>
CSS样式
css 复制代码
.content p::first-line {
  font-weight: bold;
  color: #e74c3c;
  letter-spacing: 1px;
}

.content p::first-letter {
  font-size: 200%;
  font-weight: bold;
  color: #2c3e50;
  float: left;
  padding-right: 4px;
}

效果说明 :在这个示例中,我们还额外展示了 ::first-letter 伪元素,它选中每个段落的首字母 。结合这两个伪元素,我们可以实现类似古代书籍中首字下沉首行特殊标记的排版效果。
📝 注意 :当你调整浏览器窗口大小时,第一行样式的应用范围会实时变化,但 ::first-letter 始终只影响第一个字符。

::first-line 能够生效的属性是有限的,主要集中在:

  • 字体属性
  • 颜色属性
  • 背景属性
  • text-decoration
  • text-transform
  • letter-spacingword-spacing

marginpadding 虽然可以应用,但效果可能因浏览器而异,建议在使用前查阅完整的规范文档。


六、伪元素的本质

理解伪元素的本质很重要:它们创建了虚拟的元素,这些元素存在于CSS的渲染树中,但不会出现在真实的DOM树里。这意味着:

  • ❌ 你无法通过 JavaScript 选择它们
  • ❌ 它们不会被屏幕阅读器读出(这对于 ::before::after 尤其需要注意)

七、伪类与伪元素组合使用

伪类和伪元素可以组合使用 ,这能产生非常精准的选择效果。组合时,伪类在前,伪元素在后,因为伪类选择的是整体元素的状态,而伪元素则在这个选中元素的基础上进一步定位到特定部分。

示例场景

选择文章中的第一个段落,然后只对这个段落的第一行应用样式。

HTML结构
html 复制代码
<article class="story">
  <h2>神话传说</h2>
  <p>盘古开天辟地,首出御世。天地混沌如鸡子,盘古生其中。万八千岁,天地开辟,阳清为天,阴浊为地。</p>
  <p>盘古在其中,一日九变,神于天,圣于地。天日高一丈,地日厚一丈,盘古日长一丈,如此万八千岁。</p>
  <p>天数极高,地数极深,盘古极长。后乃有三皇。数起于一,立于三,成于五,盛于七,处于九,故天去地九万里。</p>
</article>
CSS样式
css 复制代码
.story p:first-child::first-line {
  font-size: 110%;
  font-weight: bold;
  font-variant: small-caps;
  color: #8e44ad;
}

.story p:first-child::first-letter {
  font-size: 300%;
  font-weight: bold;
  color: #e67e22;
  float: left;
  margin-right: 8px;
}

🔍 执行逻辑 :首先找到 class="story" 的元素 → 找到其内部的所有 p 元素 → 从中筛选出 :first-child(即第一个 p 元素)→ 最后选中这个 p 元素的 ::first-line(第一行)。

这样的组合不仅精确而且高效,充分体现了CSS选择器的强大表达能力。

💡 进阶组合 :你也可以使用更复杂的组合,例如 :hover 伪类和 ::after 伪元素结合,可以创建鼠标悬停时在元素后面附加提示信息的效果。


八、::before 与 ::after 生成内容

::before::after 是两组非常特殊的伪元素。它们不会选中文档中已有的内容,而是在选中元素的内容之前之后 创建新的虚拟元素。这两个伪元素必须配合 content 属性 使用,content 定义了要插入的内容。

8.1 插入文本内容

使用 content 属性可以直接向页面中插入文本字符串。

HTML结构
html 复制代码
<div class="note">
  <p>请仔细阅读本协议的全部内容。</p>
</div>
CSS样式
css 复制代码
.note {
  background-color: #fef9e4;
  border-left: 4px solid #f39c12;
  padding: 12px 16px;
}

.note::before {
  content: "提示:";
  font-weight: bold;
  color: #e67e22;
  margin-right: 6px;
}

.note::after {
  content: "【重要】";
  font-size: 12px;
  color: #c0392b;
  margin-left: 8px;
}

🎨 效果 :在 .note 元素的内容之前,::before 插入了加粗的"提示:"文字;在内容之后,::after 插入了红色的小号文字"【重要】"。这种用法可以避免在HTML中硬编码这些装饰性文字,让内容和表现分离
⚠️ 可访问性警告 :通过 content 插入的纯文本不会被屏幕阅读器等辅助技术识别 。屏幕阅读器会直接忽略 ::before::after 生成的内容。因此,切勿将重要的、对理解内容必不可少的信息放在这里。这些伪元素只应该用于装饰性的、可有可无的内容。


8.2 插入图标和符号

更常见的做法是使用 content 插入图标、特殊符号或空字符串,然后通过其他CSS属性进行样式化。

HTML结构
html 复制代码
<ul class="feature-list">
  <li>响应式设计,适配各种设备</li>
  <li>代码简洁,易于维护</li>
  <li>性能优化,加载迅速</li>
</ul>
CSS样式
css 复制代码
.feature-list {
  list-style: none;
  padding-left: 0;
}

.feature-list li {
  padding: 8px 0 8px 28px;
  position: relative;
}

.feature-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: #27ae60;
  font-weight: bold;
  font-size: 18px;
}

🎯 应用场景 :这个示例移除了列表默认的项目符号,然后使用 ::before 伪元素插入了一个绿色的对勾符号。通过绝对定位,将符号精确放置在列表项内容的左侧。这种技术广泛用于创建自定义的项目符号、步骤编号、面包屑导航的分隔符等场景。


8.3 插入空内容并样式化

::before::after 最强大的用法之一是插入空字符串 ,然后把这个虚拟元素当成一个普通的块级元素来设置宽高、背景、边框等样式。这实际上是在不修改HTML结构的情况下,向页面中添加全新的视觉元素。

HTML结构
html 复制代码
<div class="card">
  <img src="example.jpg" alt="示例图片" class="card-image">
  <div class="card-content">
    <h3>产品名称</h3>
    <p>产品描述信息,突出产品的核心卖点。</p>
  </div>
</div>
CSS样式
css 复制代码
.card {
  position: relative;
  width: 300px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, #3498db, #e74c3c);
  z-index: 1;
}

🌈 效果说明 :这里的 ::before 伪元素创建了一个空的块级元素,它绝对定位在 .card 容器的顶部,占据 100% 宽度和 4px 高度,背景是一个渐变色条 。这个色条实际上是一个独立的视觉元素,但HTML中完全没有对应的标签。通过这种技术,你可以实现各种装饰性效果而无需增加无意义的 div 元素。


8.4 实际应用:CSS箭头

在Web开发中,::before::after 常被用于创建各种形状的指示箭头。其原理是利用 border 属性创建三角形,然后将两个伪元素叠加或相对定位。

实现一个指向右侧的箭头
css 复制代码
.arrow {
  display: inline-block;
  position: relative;
  padding-right: 20px;
}

.arrow::before,
.arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  border-style: solid;
}

.arrow::before {
  border-width: 6px 0 6px 8px;
  border-color: transparent transparent transparent #3498db;
  transform: translateY(-50%);
}

.arrow::after {
  border-width: 4px 0 4px 6px;
  border-color: transparent transparent transparent white;
  transform: translate(2px, -50%);
}

🔺 原理说明::before 创建了一个蓝色的箭头三角形,::after 创建了一个稍小的白色三角形偏移 2px,最终呈现出带内嵌效果的箭头图标。完全不需要使用图片或字体图标,纯CSS实现,加载速度快且可以任意缩放。


九、总结

伪类和伪元素是CSS选择器体系中极具表现力的组成部分。

类型 特点 语法
伪类 基于元素的动态状态或结构位置进行选择,如同为元素动态添加类名 单冒号 :name
伪元素 选中元素中并不独立存在的部分,或创建全新的虚拟元素 双冒号 ::name

核心要点回顾

  • 结构性伪类 (如 :first-child)让你根据元素位置精准选择
  • 动态伪类 (如 :hover:focus)提升交互体验和可访问性
  • ::first-line::first-letter 实现精美的文本排版效果
  • ::before::after 配合 content 属性,可在不修改HTML结构的前提下插入装饰性内容
  • ⚠️ 可访问性红线::before::after 生成的内容无法被屏幕阅读器识别,重要信息切勿放入其中

理解并熟练运用这些选择器,能够让你的CSS代码更加精简、语义化更强、维护成本更低 。在实际开发中,建议优先使用伪类和伪元素替代那些仅为样式服务的冗余类名,但在使用 ::before::after 插入内容时,务必注意可访问性。

🚀 进阶思考:随着对CSS的理解不断深入,你会发现这些"伪"的力量远比你想象的要强大。


还在纠结 CSS 样式写得杂乱无章、布局频频踩坑?收藏此文持续跟进,后续分享 CSS 高效简写、兼容适配方案、经典布局案例、样式避坑干货,从基础样式到实战排版一站式学透,快速提升前端页面编写能力!

相关推荐
idcu2 小时前
Lyt.js + Vite 快速开发指南
前端·typescript
暗不需求2 小时前
玩转 React Hooks:从基础到实战,逐行解析带你彻底掌握
前端·react.js·面试
一颗小青松2 小时前
css 文字区域根据图片形状显示,根据文字设置背景图
前端·css
阿黎梨梨2 小时前
跟 Git 打交道的正确姿势
前端
idcu2 小时前
深入 Lyt.js 路由系统:L6 生态系统层的核心
前端·typescript
idcu2 小时前
用 Lyt.js 构建 Todo 应用:完整教程
前端·typescript
七夜zippoe2 小时前
DolphinDB时间序列引擎:实时聚合计算
服务器·前端·时间序列·dolphindb·实时聚合
佳木逢钺2 小时前
pnpm 命令功能清单
前端
m0_738120722 小时前
渗透测试基础知识——从零认识JWT(JSON Web Token)身份令牌
服务器·前端·安全·web安全·网络安全·json