news 2026/6/14 5:47:03

第06篇:伪类详解:状态与结构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第06篇:伪类详解:状态与结构

第06篇:伪类详解:状态与结构

伪类是 CSS 选择器中最灵活、最强大的一类。它们让你能够根据元素的状态(如鼠标悬停、获得焦点)或结构位置(如第一个子元素、奇数行)来选择元素,而无需修改 HTML。掌握伪类,意味着你可以用更少的代码实现更丰富的交互效果。


学习目标

  • 掌握链接伪类(:link:visited:hover:active)及其使用顺序
  • 掌握用户交互伪类(:hover:focus:focus-visible:active:disabled
  • 掌握表单状态伪类(:checked:indeterminate:required:valid:invalid
  • 掌握结构伪类(:first-child:last-child:nth-child():nth-of-type()等)
  • 掌握现代伪类(:is():where():not():has()
  • 理解伪类的权重计算规则

核心知识点

一、什么是伪类?

伪类(Pseudo-class)用于选中处于特定状态或具有特定结构位置的元素。

/* 选中鼠标悬停时的按钮 */.btn:hover{background:#357abd;}/* 选中列表中的第一个子元素 */li:first-child{border-top:none;}/* 选中获得焦点的输入框 */input:focus{border-color:#4a90d9;}

语法特征:以冒号:开头,紧跟伪类名称,如:hover:nth-child(2n+1)

与伪元素的区别

伪类伪元素
:单冒号::双冒号(CSS3 规范)
选中已有元素的特定状态在元素前后创建虚拟内容
:hover:nth-child()::before::after

二、链接伪类(Link Pseudo-classes)

专门用于<a>标签的四个伪类,被称为“LoVe HAte”规则:

/* L - :link - 未访问过的链接 */a:link{color:#4a90d9;}/* V - :visited - 已访问过的链接 */a:visited{color:#764ba2;}/* H - :hover - 鼠标悬停时 */a:hover{color:#e74c3c;text-decoration:underline;}/* A - :active - 鼠标按下瞬间 */a:active{color:#c0392b;}

顺序很重要:必须按:link:visited:hover:active的顺序书写,否则后面的规则会覆盖前面的。

记忆口诀:LoVe HAte(爱恨)

/* ✅ 正确顺序 */a:link{color:blue;}a:visited{color:purple;}a:hover{color:red;}a:active{color:orange;}/* ❌ 错误顺序:hover 在 link 前面,link 会覆盖 hover */a:hover{color:red;}/* 先定义 */a:link{color:blue;}/* 后定义,权重相同,会覆盖 hover */

简化写法:现代浏览器中,直接写aa:hover通常就够了:

/* 简洁实用的链接样式 */a{color:#4a90d9;text-decoration:none;transition:color 0.2s;}a:hover{color:#e74c3c;text-decoration:underline;}a:visited{color:#764ba2;/* 可选:区分已访问链接 */}

三、用户交互伪类(User Action Pseudo-classes)

:hover— 鼠标悬停
/* 基础用法 */.btn:hover{background:#357abd;}/* 悬停时显示子元素(下拉菜单) */.dropdown:hover .dropdown-menu{display:block;}/* 悬停时放大图片 */.card:hover img{transform:scale(1.05);}/* 悬停时添加阴影 */.card:hover{box-shadow:0 8px 24pxrgba(0,0,0,0.15);}

注意:hover在触摸屏设备上没有"悬停"概念,通常表现为点击时的瞬间状态。不要依赖:hover展示关键内容。

:focus— 获得焦点

当元素通过鼠标点击或键盘 Tab 键获得焦点时触发。

/* 输入框获得焦点时的样式 */input:focus, textarea:focus, select:focus{outline:none;/* 移除浏览器默认轮廓 */border-color:#4a90d9;box-shadow:0 0 0 3pxrgba(74,144,217,0.2);}/* 按钮获得焦点时的样式 */button:focus{outline:2px solid #4a90d9;outline-offset:2px;}

:focus-visible— 仅在键盘聚焦时显示(现代浏览器支持)

/* 键盘 Tab 切换时显示轮廓,鼠标点击时不显示 */button:focus-visible{outline:2px solid #4a90d9;outline-offset:2px;}

优势:解决了一个长期困扰——鼠标点击按钮时出现 ugly 的 outline,但键盘导航时又需要 outline。

:active— 激活状态

元素被鼠标按下但尚未释放的瞬间,或键盘 Enter/Space 按下时。

/* 按钮按下时的反馈 */.btn:active{transform:translateY(1px);box-shadow:inset 0 2px 4pxrgba(0,0,0,0.1);}
:disabled— 禁用状态
/* 禁用状态的输入框和按钮 */input:disabled, button:disabled{background:#f0f0f0;color:#999;cursor:not-allowed;opacity:0.6;}

四、表单状态伪类(Form State Pseudo-classes)

<formclass="demo-form"><inputtype="text"requiredplaceholder="必填项"><inputtype="email"placeholder="邮箱"><inputtype="checkbox"checked><inputtype="radio"name="gender"><buttontype="submit">提交</button></form>
/* :checked - 选中的复选框/单选框 */input[type="checkbox"]:checked + label{color:#2ecc71;font-weight:bold;}/* :required - 必填字段 */input:required{border-left:3px solid #e74c3c;}/* :optional - 可选字段(非必填) */input:optional{border-left:3px solid #2ecc71;}/* :valid - 输入合法时 */input:valid{border-color:#2ecc71;}/* :invalid - 输入不合法时 */input:invalid{border-color:#e74c3c;}/* :placeholder-shown - 占位符显示时(未输入内容) */input:placeholder-shown{border-style:dashed;}/* :indeterminate - 不确定状态(如复选框的"半选"状态) */input[type="checkbox"]:indeterminate{background:#ffc107;}

表单验证样式实战

/* 优雅的表单验证反馈 */.form-field{margin-bottom:16px;}.form-field input{width:100%;padding:10px 14px;border:2px solid #ddd;border-radius:6px;transition:all 0.3s;}/* 未填写且获得焦点时 */.form-field input:focus:placeholder-shown{border-color:#ffc107;}/* 填写且合法 */.form-field input:valid{border-color:#2ecc71;}/* 填写且不合法 */.form-field input:focus:invalid{border-color:#e74c3c;}

五、结构伪类(Structural Pseudo-classes)

结构伪类根据元素在 DOM 树中的位置来选择,无需添加类名。

基础结构伪类
/* :first-child - 第一个子元素 */li:first-child{border-top:none;}/* :last-child - 最后一个子元素 */li:last-child{border-bottom:none;}/* :only-child - 唯一的子元素 */.sidebar-widget:only-child{margin:0;}/* :empty - 没有子元素(包括文本)的元素 */.error-message:empty{display:none;/* 空错误提示自动隐藏 */}
:nth-child()— 最强大的结构伪类
/* :nth-child(n) - 第 n 个子元素 */li:nth-child(3){background:#e3f2fd;/* 第三个 li 高亮 */}/* :nth-child(2n) 或 :nth-child(even) - 偶数项 */li:nth-child(even){background:#f5f5f5;}/* :nth-child(2n+1) 或 :nth-child(odd) - 奇数项 */li:nth-child(odd){background:#ffffff;}/* :nth-child(3n) - 每第 3 个 */.gallery-item:nth-child(3n){margin-right:0;}/* :nth-child(-n+3) - 前 3 个 */.top-list li:nth-child(-n+3){font-weight:bold;color:#e74c3c;}/* :nth-child(n+4) - 从第 4 个开始的所有 */.list li:nth-child(n+4){color:#999;}/* :nth-last-child(2) - 倒数第 2 个 */li:nth-last-child(2){border-bottom:2px solid #ffc107;}

:nth-child()公式速查表

公式含义选中项
nth-child(3)第 3 个3
nth-child(even)/2n偶数2, 4, 6, 8…
nth-child(odd)/2n+1奇数1, 3, 5, 7…
nth-child(3n)每第 3 个3, 6, 9, 12…
nth-child(3n+1)从 1 开始每第 3 个1, 4, 7, 10…
nth-child(-n+3)前 3 个1, 2, 3
nth-child(n+4)从第 4 个开始4, 5, 6, 7…
nth-child(n+3):nth-child(-n+5)第 3 到第 5 个3, 4, 5
:nth-of-type()— 按类型计数

:nth-child()计数时不区分元素类型,:nth-of-type()只统计同类型的兄弟元素。

<article><h2>标题 1</h2><p>段落 1</p><p>段落 2</p><h2>标题 2</h2><p>段落 3</p></article>
/* ❌ 这样写不会选中 "段落 2",因为 h2 占了第 1 个位置 */article p:nth-child(2){color:red;}/* 实际上选中了 "段落 1",因为它是 article 的第 2 个子元素 *//* ✅ 用 :nth-of-type() 只数 p 元素 */article p:nth-of-type(2){color:red;/* 正确选中 "段落 2" */}/* 给每个 h2 后面的第一个 p 加样式 */article h2 + p{font-size:1.1em;}

:nth-child()vs:nth-of-type()对比

/* 场景:表格的斑马纹 */tr:nth-child(even){}/* 偶数行(包括 thead/tr) */tr:nth-of-type(even){}/* 同类型中的偶数行 *//* 场景:只给段落设置斑马纹 */article p:nth-of-type(odd){}/* ✅ 正确 */article p:nth-child(odd){}/* ❌ 可能被其他元素打乱 */

六、现代伪类(Modern Pseudo-classes)

:not()— 否定伪类

选中不匹配选择器的元素。

/* 选中所有非 disabled 的按钮 */button:not(:disabled){cursor:pointer;}/* 选中所有不含 .active 类的 li */li:not(.active){opacity:0.7;}/* 选中不是第一个也不是最后一个的 li */li:not(:first-child):not(:last-child){margin:8px 0;}/* CSS4 支持传入选择器列表(现代浏览器) */li:not(:first-child, :last-child){margin:8px 0;}

注意:not()不能嵌套伪元素,且内部的复杂选择器在现代浏览器才支持。

:is()— 匹配列表中的任意一个

简化复杂的选择器群组。

/* ❌ 冗长的写法 */h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover{color:#e74c3c;}/* ✅ 用 :is() 简化 */:is(h1, h2, h3, h4) a:hover{color:#e74c3c;}/* 减少重复 */article :is(h1, h2, h3){color:#1a1a2e;line-height:1.3;}/* 相当于: article h1, article h2, article h3 { color: #1a1a2e; line-height: 1.3; } */

:is():where()的区别

:is():where()
权重取参数中最高的权重权重永远为0
用途简化选择器并保持权重简化选择器且不增加权重
/* :is() 的权重 = .class (10) */:is(h1, .title, #header){}/* 权重 = 0-1-0 = 10 *//* :where() 的权重 = 0 */:where(h1, .title, #header){}/* 权重 = 0-0-0 = 0 */
:has()— 父选择器(现代浏览器支持)

选中包含特定子元素的父元素——这是 CSS 长期以来的重大突破!

/* 选中包含 img 的 figure 元素 */figure:has(img){border:1px solid #ddd;padding:10px;}/* 选中包含 figcaption 的 figure */figure:has(figcaption){background:#f8f9fa;}/* 选中后面紧跟 ul 的 li(二级菜单项) */li:has(> ul){position:relative;}/* 选中后面紧跟 ul 的 li 的 a(有下拉菜单的导航项) */li:has(> ul) > a::after{content:" ▼";font-size:0.8em;}/* 表单验证:选中包含非法输入的字段容器 */.form-field:has(input:invalid) .error-msg{display:block;}

七、伪类的优先级权重

伪类(如:hover:nth-child())的权重等同于类选择器,即10

/* 权重计算 */.btn:hover{}/* 10 + 10 = 20 */li:first-child{}/* 1 + 10 = 11 */input:focus:invalid{}/* 1 + 10 + 10 = 21 */:is(#header, .nav){}/* 取最高 = 100(ID 的权重) */:where(#header){}/* 权重 = 0 */

动手练习

练习 1:导航栏悬停效果

实现一个导航栏,要求:

  • 普通链接为灰色
  • 鼠标悬停时变为蓝色并出现下划线动画(下划线从中间向两侧展开)
  • 当前页面链接(.active)为蓝色且始终显示下划线
  • 已访问过的链接为紫色(但不超过 10% 的透明度区别)

练习 2:斑马纹表格

给定以下 HTML,用:nth-child实现斑马纹效果:

<tableclass="data-table"><thead><tr><th>姓名</th><th>年龄</th><th>城市</th></tr></thead><tbody><tr><td>张三</td><td>25</td><td>北京</td></tr><tr><td>李四</td><td>30</td><td>上海</td></tr><!-- 更多行... --></tbody></table>
  • tbody 中的行奇偶不同背景色
  • 鼠标悬停时行高亮
  • 第一列的文字加粗

练习 3::has()实战

:has()实现以下效果(如果浏览器不支持,用其他方式回退):

  • 包含图片的.card有更大的上内边距
  • .form-group中有input:invalid时,对应的label变红色
  • 选中后面紧跟.details.summary并添加箭头图标

常见误区 ⚠️

误区真相
:hover在手机上也能用”触摸屏没有"悬停"概念,:hover在手机上表现不一致,不要依赖它展示关键内容
:focus:focus-visible是一回事”:focus-visible只在键盘聚焦时触发,鼠标点击时不触发,更适合现代交互
:nth-child(2n):nth-of-type(2n)效果一样”当父元素中有多种类型子元素时,两者结果完全不同
:not()可以嵌套任何选择器”:not()内部传统上只能写一个简单选择器,现代浏览器支持选择器列表
:is():where()完全一样”:is()取参数中最高权重,:where()权重永远为 0
:visited可以设置任意样式”出于隐私保护,浏览器限制:visited只能设置colorbackground-colorborder-coloroutline-color
:has()可以无限嵌套”:has()不能嵌套:has(),且性能开销较大,应谨慎使用
“结构伪类会动态更新”当 DOM 变化时结构伪类会自动重新计算,不需要刷新页面

速查卡片 📋

链接伪类顺序(LoVe HAte)

a:link{}/* L - 未访问 */a:visited{}/* V - 已访问 */a:hover{}/* H - 悬停 */a:active{}/* A - 按下 */

结构伪类速查

伪类选中
:first-child第一个子元素
:last-child最后一个子元素
:only-child唯一的子元素
:nth-child(n)第 n 个子元素
:nth-last-child(n)倒数第 n 个子元素
:first-of-type同类型中的第一个
:last-of-type同类型中的最后一个
:nth-of-type(n)同类型中的第 n 个
:empty无子元素(含文本)

:nth-child()公式速查

公式效果
even/2n偶数项
odd/2n+1奇数项
3n每第 3 个
-n+3前 3 个
n+4从第 4 个开始

现代伪类

伪类作用权重
:is()匹配列表中任意一个取最高
:where()匹配列表中任意一个0
:not()排除匹配的元素取参数权重
:has()包含特定子元素的父元素复杂

扩展阅读

  • MDN: 伪类
  • MDN: :nth-child()
  • MDN: :has() — 父选择器
  • MDN: :is()
  • CSS-Tricks: :nth-child() recipes(英文)
  • Can I Use :has() — 查询浏览器支持

📌配套代码

  • CODE/06/pseudo-class-states.html — 状态伪类交互演示
  • CODE/06/pseudo-class-structure.html — 结构伪类布局演示

🎉下一步:进入 第07篇:伪元素详解,学习用::before::after创建虚拟内容。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 5:45:59

SD-PPP:Photoshop AI插件终极指南,重新定义创意工作流

SD-PPP&#xff1a;Photoshop AI插件终极指南&#xff0c;重新定义创意工作流 【免费下载链接】sd-ppp A Photoshop AI plugin 项目地址: https://gitcode.com/gh_mirrors/sd/sd-ppp 在当今AI绘图技术飞速发展的时代&#xff0c;设计师们面临着一个共同的挑战&#xff1…

作者头像 李华
网站建设 2026/6/14 5:44:15

别再手动处理图片特征了!用Milvus + Towhee 5分钟搞定一个以图搜图Demo

5分钟构建以图搜图系统&#xff1a;Milvus与Towhee的高效组合实践 在数字内容爆炸式增长的今天&#xff0c;快速准确地检索图像已成为众多应用的核心需求。传统的关键词搜索在面对海量非结构化图像数据时显得力不从心&#xff0c;而以图搜图技术正逐渐成为解决这一痛点的利器。…

作者头像 李华
网站建设 2026/6/14 5:39:07

5分钟上手知乎数据获取:JavaScript开发者必备的zhihu-api实战指南

5分钟上手知乎数据获取&#xff1a;JavaScript开发者必备的zhihu-api实战指南 【免费下载链接】zhihu-api Unofficial API for zhihu. 项目地址: https://gitcode.com/gh_mirrors/zhi/zhihu-api 在知乎海量内容中挖掘有价值的数据&#xff0c;是许多开发者和数据分析师面…

作者头像 李华
网站建设 2026/6/14 5:37:14

多维聚合中的数据变形:从索引重塑到维度广播的系统性实践

1. 这不是简单的“分组求和”——多维聚合中的数据变形本质 你手头有一张销售表&#xff0c;字段包括地区、产品线、季度、销售额、成本、客户等级。现在老板要你交三份报表&#xff1a;第一份按地区产品线看累计毛利&#xff1b;第二份按季度客户等级看平均单笔订单金额&#…

作者头像 李华
网站建设 2026/6/14 5:35:11

Claude 3.5 Sonnet移除推理层对逻辑系统的影响与适配

1. 项目概述&#xff1a;这不是一次普通更新&#xff0c;而是模型能力边界的悄然坍缩“Anthropic Just Shipped the Layer That’s Already Going to Zero”——这个标题乍看像科技媒体的耸动标题党&#xff0c;但如果你在2023–2024年深度用过Claude系列模型&#xff0c;尤其是…

作者头像 李华
网站建设 2026/6/14 5:23:10

如何快速将B站缓存视频转换为MP4:一键解决格式兼容问题

如何快速将B站缓存视频转换为MP4&#xff1a;一键解决格式兼容问题 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾为B站缓存视频无法在…

作者头像 李华