:nth-child(-n+3)能选前三个子元素,但因按所有子元素位置计数,混有其他标签时会误选;应优先用:nth-of-type(-n+3)只统计同类型元素。

为什么 :nth-child(-n+3) 能选前三个,但常被误用?
它确实能选中前三个子元素,但关键在于:它匹配的是「在父容器中位置为第 1、2、3 的子元素」,而不是「列表中前三个 <li> 元素」。如果父元素里混有其他类型标签(比如 <div>、<code><p></p>),:nth-child(-n+3) 会把它们一起算进去——导致真正想选的 <li> 可能一个都选不中。
:nth-child(-n+3) 和 :nth-of-type(-n+3) 的区别在哪?
前者按 DOM 顺序数所有子元素,后者只数同类型(比如只数 <li>)。实际写列表样式时,绝大多数情况该用后者:
ul li:nth-of-type(-n+3) {
color: red;
}
常见错误场景:
- HTML 是
<ul> <div>header</div> <li>A</li> <li>B</li> <li>C</li> </ul>→:nth-child(-n+3)会选中<div> 和前两个 <code><li>,不是你想要的 - 用
:nth-child(-n+3)给<ol></ol>加序号样式,但中间插了<li class="separator">→ 序号错位
怎么验证当前选择器到底选中了谁?
打开浏览器开发者工具,在 Elements 面板里右键目标元素 → 「Break on > attribute modifications」没用,直接用控制台跑这行:
立即学习“前端免费学习笔记(深入)”;
console.log([...document.querySelectorAll('ul li:nth-child(-n+3)')]);
再对比:
console.log([...document.querySelectorAll('ul li:nth-of-type(-n+3)')]);
两者输出数组长度和内容不同,就说明存在类型干扰。另外注意::nth-child() 不接受元素类型前缀(不能写 li:nth-child(-n+3) 来限定,必须靠父选择器约束)。
兼容性和性能要注意什么?
:nth-child() 和 :nth-of-type() 在 IE9+ 都支持,不用垫片。性能上无明显差异,但若列表动态增删(比如 Vue/React 渲染),:nth-child() 更容易因插入非 <li> 节点而意外失效——这点常被忽略,尤其在组件封装时,父容器可能被外层逻辑注入额外节点。


















