:first-child匹配父元素第一个子节点且类型必须完全一致,受空白、注释、其他标签干扰;:first-of-type才按同类型首个匹配,更符合实际需求。

:first-child 看的是 DOM 位置,不是你“觉得”哪个是第一个
它只匹配父元素下「第一个子节点」且「恰好是你写的那个标签」。哪怕结构里只多了一个换行、空格、注释,或者前面插了个 <header></header>,:first-child 就立刻失效——因为它选的不是“第一个 li”,而是“父元素的第一个子节点是不是 li”。
怎么确认是不是被空白或注释卡住了
打开浏览器开发者工具(F12),展开父元素,逐个看子节点:
- 如果第一个子节点是
#text(内容为空或只有换行/空格),那你的目标元素就不是:first-child - 如果第一个是
<!-- 注释 -->,同理失效 - 如果第一个是
<h3></h3>或<div class="intro">,而你写的是 <code>li:first-child,那它永远不匹配:first-of-type 才是你真正想用的大多数时候
:first-of-type不关心前面有没有别的标签,只找「同类型中第一个出现的」。比如:-
p:first-of-type→ 选父元素里第一个<p></p>,不管它前面有没有<h2></h2>或文本 -
button:first-of-type→ 在按钮组混有<input type="button">时仍能稳稳命中第一个<button></button> - 注意:
:first-of-type不支持 IE8 及更早版本;如需兼容,得手动加class="first"
Flex/Grid 里 order 或 grid-template-areas 会骗过你的眼睛
视觉顺序变了,但
:first-child还按原始 HTML 顺序来:-
display: flex; flex-direction: column-reverse;→ 最后一个元素显示在最上面,但:first-child依然作用于 DOM 中第一个子元素 -
grid-template-areas重排了布局?不影响子节点在 DOM 树里的先后顺序 - 想按视觉顺序控制样式?别依赖伪类,改用 JS 动态加 class,或提前在模板里注入语义化 class
最容易被忽略的一点:伪类无法穿透 Shadow DOM。
:first-child在自定义组件内部写,只对 shadow root 里的子节点生效,对外部传入的<slot></slot>内容无效。 -











