:first-of-type只匹配父元素下同标签名的第一个元素节点;它不看是否为首个子节点,忽略文本、注释等非元素节点,且作用域仅限直接父级,ie8及以下不支持。

直接说结论::first-of-type 只匹配「父元素下同标签名的第一个元素节点」,不看它是不是第一个子节点,也不管前面有没有 h2、div 或空格换行——只要它是所有同类型元素中最早出现的那个,就命中。
为什么 p:first-of-type 有时没生效?
不是选择器写错了,而是你误判了“谁是它的父元素”或“哪些节点算‘同类型’”:
-
p:first-of-type的作用域永远只在**直接父级**内计算,不会穿透到祖父级或跨容器;比如.sidebar p:first-of-type会匹配侧边栏里每个<div class="card"><p>...</p></div>中各自的首个p,而不是整个.sidebar下第一个p - 文本节点(哪怕只是回车或空格)、
<!-- comment -->、<script></script>都被跳过,不参与“类型分组”,但它们仍是子节点——所以如果你写的是div > p:first-of-type,而div的第一个子节点是注释,那没问题;可如果写成div p:first-of-type(后代选择器),就可能意外匹配到嵌套更深的p - IE8 及更早版本完全不支持
:first-of-type,构建时若用了旧版 Autoprefixer,可能生成无效回退代码,导致样式消失
怎么写才真正选中“文章正文第一个段落”?
别依赖模糊的上下文,用组合选择器收窄作用域:
- 优先用子选择器:
.article > p:first-of-type—— 确保只看.article的直接子p,排除侧边栏、卡片等干扰结构 - 加 class 更稳:
.article .lead:first-of-type或.article p.intro:first-of-type,避免仅靠标签名带来的歧义 - 如果结构固定(如总是
<h2></h2> <p></p>),p:first-of-type和p:nth-of-type(1)效果一致,但前者语义更清晰 - 千万别用
*:first-of-type—— 它会把<meta>(如果误放在)、<script></script>、<svg></svg>全部套上样式,极难调试
和 :first-child 混用时为啥样式不对?
两者权重相同,层叠顺序决定最终效果,不是“更精确就优先”:
-
p:first-child要求该p必须是父元素的第一个子节点;p:first-of-type只要求它是所有p中的第一个——二者条件不同,可能同时满足,也可能互斥 - 如果写了
p:first-child { color: red; }再写p:first-of-type { color: blue; },且某个p同时满足两个条件,那它最终是蓝色 - 想确保“首个子元素且是
p”,应写p:first-child;想确保“不管前面有什么,只要它是第一个p”,就用p:first-of-type;二者目的不同,不能互相替代
最易被忽略的一点::first-of-type 的“类型”只认标签名(或伪元素类型),完全不看 class、id、属性或内容。哪怕你给第一个 p 加了 class="hidden",它照样匹配 p:first-of-type —— 因为判定发生在样式计算阶段,不读取运行时状态。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











