nth-child按父元素所有子元素顺序计数(从1开始),含标签、文本、注释节点;nth-of-type仅按同类型标签计数;n代入从0开始,但序号从1起算。

nth-child 选不中元素,大概率是索引算错了
它不是按“你在 HTML 里写的第几个 <div>”来数,而是按“父元素下所有同级子元素的顺序”来数,且从 1 开始。哪怕中间夹着 <code><p></p>、<span></span> 或注释节点,都会被计入索引。
常见现象:div:nth-child(2) 没生效,但你明明写了两个 <div> —— 很可能第一个是 <code><h2></h2>,第二个才是 <div>,那这个 <code><div> 实际是第 2 个子元素,但它的索引是 2,所以能命中;但如果它是第 3 个子元素(前面有 <code><h2></h2> 和 <p></p>),div:nth-child(2) 就完全匹配不到。
nth-child(n) 和 nth-of-type(n) 的关键区别
nth-child 看位置,nth-of-type 看标签类型。这是最常混淆的点。
-
div:nth-child(2):父元素的第 2 个子元素必须是<div>,否则不匹配 <li> <code>div:nth-of-type(2):父元素下所有<div> 中的第 2 个,不管它前面有多少其他标签 <p>示例结构:</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/ai/2024" title="畅图"><img src="https://img.php.cn/upload/ai_manual/000/000/000/175679986468670.png" alt="畅图" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a href="/ai/2024" title="畅图">畅图</a> <p>AI可视化工具</p> </div> <a href="/ai/2024" title="畅图" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <pre class="brush:php;toolbar:false;"><section> <h2>标题</h2> <p>说明</p> <div>第一个 div</div> <div>第二个 div</div> </section></pre> <p>此时:<br> – <code>div:nth-child(3)✅ 匹配第一个<div>(它是第 3 个子元素)<br> – <code>div:nth-child(4)✅ 匹配第二个<div> <br> – <code>div:nth-of-type(2)✅ 同样匹配第二个<div>,但写法更稳定、语义更准 <h3>伪类里的 n 是从 0 还是 1 开始?</h3> <p>n 始终从 0 开始代入计算,但最终匹配的是「结果序号」,而序号本身从 1 开始计数。比如 <code>:nth-child(2n)展开为 2×0=0(无效)、2×1=2(第 2 个)、2×2=4(第 4 个)…… 所以它选的是偶数位子元素。容易踩的坑:
-
:nth-child(0)永远不匹配(没有第 0 个元素) -
:nth-child(-n+3)匹配前 3 个子元素(n=0→3,n=1→2,n=2→1,n=3→0 无效) - 写
:nth-child(1)和:first-child效果一样,但前者多一次计算,后者语义清晰且性能略优
用开发者工具快速验证 nth-child 是否生效
别靠猜。在 Chrome DevTools 的 Elements 面板中:
- 右键目标元素 → “Break on” → “attribute modifications” 不适用,改用直接看 Styles 面板右侧是否列出该选择器
- 更可靠的做法:在 Console 中运行
document.querySelector('div:nth-child(2)'),看返回值是不是你要的元素 - 如果返回
null,用Array.from(el.parentNode.children).map((c, i) => [i+1, c.nodeName])打印出所有子元素的序号和标签名,一眼看清索引分布
复杂嵌套或动态插入内容时,DOM 实际结构往往和模板文件不一致——注释、空格文本节点、服务端渲染残留、JS 插入的占位符,都可能悄悄改变子元素顺序。
-







