:first-child要求元素必须是父容器的第一个子节点,而:first-of-type只匹配同类型元素中首个出现的;前者易受注释、空格或前置标签影响,后者更适用于找某类元素的第一个实例。

为什么 :first-child 有时选不到想要的第一个元素
因为 :first-child 要求目标元素**必须是父容器的第一个子节点**,且类型不限。如果父容器最前面是个 <p></p>,后面才是 <div>,那 <code>div:first-child 就完全不匹配——哪怕它是页面里第一个 <div>。
<p>常见错误场景:</p>
<ul>
<li>用 <code>li:first-child 想高亮列表第一项,但实际 HTML 开头有注释或空格文本节点(虽然不可见,但仍是子节点)
<slot></slot>、<template></template> 或服务端注入的提示 <span class="hint"></span>,导致目标元素失去“第一个”位置什么时候该用 :first-of-type
:first-of-type 只关心**同类型标签中的第一个**,忽略中间夹杂的其他标签。它更适合“找某类元素的第一个实例”这种语义。
例如:
立即学习“前端免费学习笔记(深入)”;
div > p:first-of-type { color: red; }
只要父 <div> 下有至少一个 <code><p></p>,且它是所有 <p></p> 中 DOM 顺序最靠前的,就会命中——不管前面有没有 <h2></h2>、<ul></ul> 或文本节点。
注意点:
- 类型指 HTML 标签名,
p和P在 HTML 中等价,但和section、article严格区分 - 不识别 class 或属性,
.item:first-of-type不会只找带item类的第一个元素,而是找所有<div>(假设选择器是 <code>div.item:first-of-type)中第一个<div>,再检查它是否有 <code>item类真实 DOM 结构下两者的差异演示
看这段 HTML:
<article> <h2>标题</h2> <p>第一段</p> <div>说明块</div> <p>第二段</p> </article>
此时:
-
article > p:first-child→ ❌ 不匹配(<p></p>不是<article></article>的第一个子元素) -
article > p:first-of-type→ ✅ 匹配第一个<p></p>(即“第一段”) -
article > :first-child→ ✅ 匹配<h2></h2>(通配符 + first-child) -
article > :first-of-type→ ✅ 同样匹配<h2></h2>(它是所有同类型元素中第一个<h2></h2>)
精准定位建议:别只靠伪类,结合 class 更可靠
伪类依赖 DOM 结构顺序,而结构容易被动态插入、SSR 注入或 CMS 模板改动破坏。真正需要“第一个内容区块”“首条新闻”这类语义时,优先考虑:
- 后端或构建时加明确 class,如
<div class="news-item news-item--first"> <li>用 JS 动态标记:<code>document.querySelector('.news-item').classList.add('is-first') - 若必须用 CSS,组合使用更稳妥:
.news-item:first-of-type:not(.sponsored)排除广告占位
伪类不是银弹,尤其在现代框架(React/Vue)中,DOM 节点可能被 Fragment、条件渲染或 Portal 打乱,
:first-of-type看似宽松,其实也可能跨过预期边界。 -










