:first-child不生效是因为它严格匹配父元素的第一个子节点且必须是目标标签;若前面有注释、空格文本节点或其他元素,则失效,此时应改用:first-of-type。

为什么 :first-child 有时不生效
因为 :first-child 匹配的是「父元素下第一个子节点,且该节点恰好是你写的那个标签」。它不关心类型是否匹配,只看位置——如果父元素第一个子节点是 <p></p>,而你写的是 div:first-child,那这个 div 就永远选不到,哪怕它是第二个子元素。
常见错误现象:li:first-child 没加粗,但 HTML 里第一个 <li> 前面有注释、空格文本节点,或一个 <h3></h3> 标题——这些都会让 <li> 失去「第一个子元素」的身份。
- 检查 DOM 结构:用浏览器开发者工具看父容器的子节点顺序,注意隐藏的文本节点(比如换行缩进)
- 若父元素开头有其他标签(如
<header></header>或<span></span>),:first-child就不适用 - 想忽略非目标标签只找第一个
li?用:first-of-type更稳妥
:first-child 和 :first-of-type 的关键区别
:first-child 看位置,:first-of-type 看类型+顺序。比如父元素内是 <div></div>
<p>A</p>
<p>B</p>:
-
p:first-child→ 不匹配(<p></p>是第二个子节点) -
p:first-of-type→ 匹配第一个<p></p>(即内容为 A 的那个)
性能上两者无差异,但语义不同:如果你要样式化「列表中首个条目」,且确定列表结构干净(无前置节点),用 :first-child;如果列表可能被标题、说明文字等打断,优先选 :first-of-type。
在 Flex/Grid 容器中 :first-child 还管用吗
管用,但要注意:CSS 布局方式(display: flex 或 grid)不影响 DOM 树结构,所以 :first-child 依然按 HTML 子节点顺序匹配。
不过容易踩的坑:
- Flex 容器里用了
order属性——视觉顺序变了,但 DOM 顺序没变,:first-child仍选原始第一个子元素 - Grid 中用
grid-template-areas重排了元素位置,同样不改变:first-child的判断依据 - 如果用
flex-direction: column-reverse,第一个子元素在视觉底部,但:first-child依然作用于 DOM 中的第一个
替代方案:当 :first-child 不够用时怎么办
真遇到复杂嵌套或动态插入场景,纯 CSS 有时力不从心。这时可考虑:
- 加 class 控制:
<li class="first">,比依赖结构更可靠 - 用 JS 动态标记:
parent.children[0].classList.add('first'),尤其适合 AJAX 加载后的内容 - 如果目标是「某类元素中的第一个」,且浏览器支持较新,可用
:is(li, p):first-of-type(注意兼容性)
最常被忽略的一点:CSS 伪类无法穿透 Shadow DOM。如果你在自定义组件内部写 :first-child,它只对组件 shadow root 内的子节点有效,对外部传入的 slot 内容无效——这时候必须靠 JS 或暴露 class 接口。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











