nth-child(n)需同时满足位置与标签类型,从首子节点计数(含文本节点);nth-of-type(n)仅按同标签顺序编号,忽略其他节点类型。

nth-child(n) 要求“位置+类型”双满足
:nth-child(n) 从父元素的第一个子节点开始数,包括 <p></p>、<div>、注释、甚至换行产生的空白文本节点——只要它排在第 <code>n 位,且恰好是你写的标签名(比如 p),才匹配成功。
常见失效现象:
-
p:nth-child(2)不生效?很可能第 2 个子节点是<div> 或一段缩进空格(DOM 中的文本节点) <li>图文混排时插了个 <code><figure></figure>,后面所有p:nth-child(n)的序号全偏了 - 用
ul li:nth-child(2)想高亮第二个列表项,但ul开头有<h3></h3>,那就根本选不到 - 中间插
<aside></aside>或<blockquote></blockquote>不影响编号 - 适合卡片列表、文章段落等结构不严格的场景
- 注意:它不识别 class 或属性,只认 HTML 标签名(
p、li、span等) -
:nth-child(2)→ 只匹配<span>B</span> -
:nth-of-type(2)→ 同时匹配<p>C</p>和<span>D</span> - 用原生
document.querySelectorAll('p:nth-of-type(2)')(现代浏览器都支持) - 手动过滤:
$('p').eq(1)(取第二个p元素,索引从 0 开始) - 避免在 jQuery 选择器里混用
:nth-of-type,尤其要兼容 IE 或旧版移动端
nth-of-type(n) 只按同标签顺序计数
:nth-of-type(n) 完全忽略其他类型节点,只在所有同类型兄弟中单独编号。比如 p:nth-of-type(2) 就是“父元素下第二个 <p></p>”,不管它前面有几个 <div>、<code><h3></h3> 或注释。
这个行为更贴近日常直觉,也更鲁棒:
不写标签前缀时的行为差异
如果写成 :nth-child(2)(没指定标签),它会选中父元素下第 2 个任意子元素;而 :nth-of-type(2) 会分别对每种标签类型各自计数——即可能同时匹配多个元素。
例如父元素内有:<p>A</p>、<span>B</span>、<p>C</p>、<span>D</span>:
jQuery 不支持 :nth-of-type 是历史遗留坑
如果你在 JS 里用 $('p:nth-of-type(2)'),老版本 jQuery(≤3.4)会直接报错或静默失败——它只解析 :nth-child,把 :nth-of-type 当作无效选择器丢弃。
替代方案:
:nth-child 却没意识到 DOM 中那些看不见的文本节点,调试起来就会卡很久。











