【H5 前端开发笔记】第 20 期:CSS 选择器 (5) —— 子元素伪类选择器 详解(结构伪类 / Structural Pseudo-classes)
这一期重点讲解 基于文档树结构 的伪类(也叫树结构伪类),它们不依赖类、ID、属性,而是根据元素在父元素中的位置关系来选择,非常适合做列表、表格、网格、卡片组的“隔行变色”“首尾特殊处理”“循环条纹”等效果。
这些伪类在 CSS3 Selectors 中引入,现代浏览器(2026 年)全部完美支持。
一、核心子元素结构伪类一览表
| 伪类 | 含义 | 计数依据 | 从哪数起? | 常用场景 | 特异性 |
|---|---|---|---|---|---|
:first-child | 作为父元素的第一个子元素 | 所有子元素 | 从前 | 去掉第一个元素的上边距 | 0,1,0 |
:last-child | 作为父元素的最后一个子元素 | 所有子元素 | 从后 | 去掉最后一个元素的下边距 | 0,1,0 |
:only-child | 父元素唯一的子元素 | 所有子元素 | — | 单条数据时的特殊样式 | 0,1,0 |
:first-of-type | 同类型标签中第一个 | 同标签类型的子元素 | 从前 | 文章中第一个 p 加粗标题感 | 0,1,0 |
:last-of-type | 同类型标签中最后一个 | 同标签类型的子元素 | 从后 | 去掉最后一个段落下边距 | 0,1,0 |
:only-of-type | 同类型标签中唯一的一个 | 同标签类型的子元素 | — | 只有一个 h2 时放大显示 | 0,1,0 |
:nth-child(n) | 第 n 个子元素(公式) | 所有子元素 | 从前 | 隔行变色、3列循环、1+4n 等 | 0,1,0 |
:nth-last-child(n) | 倒数第 n 个子元素(公式) | 所有子元素 | 从后 | 最后 3 个元素特殊处理 | 0,1,0 |
:nth-of-type(n) | 同类型中第 n 个(公式) | 同标签类型的子元素 | 从前 | 只给 p 标签隔行变色 | 0,1,0 |
:nth-last-of-type(n) | 同类型中倒数第 n 个(公式) | 同标签类型的子元素 | 从后 | 最后一个 li 不同样式 | 0,1,0 |
二、最重要区别:child vs of-type
- :nth-child / :first-child / :last-child → 看“出生顺序”,不管标签是什么,只要是第几个孩子就行
- :nth-of-type / :first-of-type / :last-of-type → 只在同类兄弟中排名,先过滤标签类型,再数第几个
<!-- 经典面试题场景 -->
<ul>
<h3>标题</h3>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
<p>说明文字</p>
<li>第四项</li>
</ul>
li:first-child { } /* 没选中,因为第一个孩子是 h3 */
li:first-of-type { } /* 选中 → 第一个 li(“第一项”) */
li:nth-child(3) { } /* 选中 → 第3个孩子是 li(“第三项”) */
li:nth-of-type(3) { } /* 选中 → 第三个 li(“第四项”) */
三、:nth-child / :nth-of-type 公式速查(敲代码必备)
| 写法 | 选中元素序号(从 1 开始) | 口诀 / 常见用途 |
|---|---|---|
:nth-child(5) | 正好第 5 个 | 固定第几个 |
:nth-child(odd) | 1,3,5,7… | 奇数行 / 斑马纹 |
:nth-child(even) | 2,4,6,8… | 偶数行 |
:nth-child(3n) | 3,6,9,12… | 每3个一组 |
:nth-child(3n+1) | 1,4,7,10… | 1、4、7…(常用于三分栏第一列) |
:nth-child(-n+3) | 1,2,3 | 前 3 个 |
:nth-child(n+4) | 4,5,6… | 从第 4 个开始 |
:nth-child(4n+2) | 2,6,10,14… | 2、6、10…(常用于卡片布局) |
-n+ 写法很强大:-n+5 = 前 5 个
四、实战代码示例(建议全部运行一遍)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>结构伪类演示</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 900px; margin: 2rem auto; }
section { margin: 3rem 0; padding: 1.5rem; border: 1px dashed #aaa; border-radius: 8px; }
/* 经典隔行变色 */
.zebra li:nth-child(odd) {
background: #f0f8ff;
}
.zebra li:nth-child(even) {
background: #fffaf0;
}
/* 前3个加粗,最后一个红色 */
.special li:nth-child(-n+3) {
font-weight: bold;
}
.special li:last-child {
color: #d32f2f;
font-style: italic;
}
/* 只针对 p 标签的 of-type 用法 */
article p:first-of-type {
font-size: 1.3em;
border-left: 5px solid #4caf50;
padding-left: 1rem;
margin-left: 0;
}
article p:nth-of-type(2n) {
color: #555;
font-style: italic;
}
/* 卡片布局:每行第1个左对齐,第3个右对齐 */
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}
.cards > div:nth-child(3n+1) { justify-self: start; }
.cards > div:nth-child(3n+2) { justify-self: center; }
.cards > div:nth-child(3n) { justify-self: end; }
/* only-child 场景:只有一个孩子时放大 */
.single > :only-child {
font-size: 2em;
color: #1976d2;
text-align: center;
}
</style>
</head>
<body>
<section class="zebra">
<h3>隔行变色(nth-child)</h3>
<ul>
<li>苹果</li><li>香蕉</li><li>橙子</li><li>梨</li><li>葡萄</li><li>西瓜</li>
</ul>
</section>
<section class="special">
<h3>前三 + 最后一个特殊</h3>
<ul>
<li>置顶公告1</li><li>置顶公告2</li><li>置顶公告3</li>
<li>普通消息A</li><li>普通消息B</li><li>普通消息C</li><li>重要结尾!</li>
</ul>
</section>
<section>
<h3>文章首段突出(first-of-type)</h3>
<article>
<h2>标题</h2>
<p>这是第一段,会被放大和加绿线。</p>
<p>第二段斜体灰色。</p>
<p>第三段正常。</p>
<p>第四段又斜体灰色。</p>
</article>
</section>
<section class="cards">
<h3>3列卡片布局对齐(nth-child 3n系列)</h3>
<div style="background:#e3f2fd;padding:1rem;">卡1</div>
<div style="background:#e8f5e9;padding:1rem;">卡2</div>
<div style="background:#fff3e0;padding:1rem;">卡3</div>
<div style="background:#f3e5f5;padding:1rem;">卡4</div>
<div style="background:#e0f7fa;padding:1rem;">卡5</div>
<div style="background:#f1f8e9;padding:1rem;">卡6</div>
</section>
<section class="single">
<h3>只有一个孩子时特殊样式(only-child)</h3>
<div>只有我一个 → 会变大变蓝</div>
</section>
<section class="single">
<h3>有多个孩子 → 普通</h3>
<div>普通A</div>
<div>普通B</div>
</section>
</body>
</html>
五、高频面试/实战总结
- 表格/列表隔行变色 →
:nth-child(odd/even)最常用 - 去掉首/尾边距 →
:first-child/:last-child去 margin/padding - 响应式网格最后一行对齐 →
:nth-child(3n)/4n等 - 文章排版首段/首图特殊 →
:first-of-type - 面包屑 / 步骤条最后一个不同 →
:last-child/:last-of-type - 避免“幽灵元素”干扰 → 用
-of-type更稳(当 HTML 结构可能插入其他标签时)
六、小坑 & 提示
:nth-child(n)的 n 从 1 开始(不是 0)- 这些伪类不考虑 display:none 的元素(仍然按 DOM 顺序计数)
- 特异性都是 0,1,0,和 class 相同,容易被更高特异性覆盖
- 不要滥用复杂公式,代码可读性第一
下一期预告:伪类(下)—— 交互 & 状态伪类(:hover / :focus / :active / :checked / :disabled / :required …)
有特别想看的场景或公式欢迎留言~
祝大家结构伪类用得丝滑!🎨