:first-of-type匹配同类型中第一个元素,非首个子元素;如p:first-of-type选所有p中首个,span:first-of-type选所有span中首个;文本/注释节点不参与类型计算;需选首个子元素应使用:first-child。

first-of-type 选不到第一个子元素?先看它到底匹配什么
first-of-type 不是“第一个子节点”,而是“同类型中第一个”。比如 <div><p>A</p><span>B</span><p>C</p></div>,两个 p 中只有第一个 p 匹配 p:first-of-type,但 span 不会因为排第二就被忽略——它自己就是 span:first-of-type。
常见错误现象:div:first-of-type 在父容器里没生效,其实是因为父容器下第一个子节点是 h2,而 div 是第三个子节点,但它仍是所有 div 中的第一个,所以仍会命中。
- 只看标签名(或伪元素类型),不看顺序位置
- 文本节点、注释节点、
<!-- -->不参与类型计算 - 若想选“第一个子元素,不管是什么类型”,该用
:first-child
想让首个 p 和首个 ul 都有特殊样式,怎么写最稳
直接写多个选择器,别偷懒合并——p:first-of-type, ul:first-of-type 清晰且无歧义。有人试过 *:first-of-type,结果所有标签类型首个都套上了样式,连 script 和 meta(如果意外出现在 body 内)都被捕获,反而失控。
- 避免用通配符
*搭配:first-of-type,语义太宽泛 - 如果结构固定,比如总是
h2开头再跟p,那p:first-of-type实际等价于p:nth-of-type(1),但前者更易读 - 注意嵌套:子容器里的
first-of-type只在它自己的父级内计算,不影响外层
IE8 不支持 first-of-type?兼容方案怎么选
IE8 及更早版本完全不识别 :first-of-type,连带不支持 :nth-of-type 等。如果必须兼容,别指望 CSS hack 补救,得换思路。
立即学习“前端免费学习笔记(深入)”;
- 服务端或 JS 注入 class,比如
<p class="first-p">,再写.first-p规则 - 用
:first-child+ 类型判断兜底:如果首个子元素恰好就是你要的标签(如<div><p>...</p></div>),那p:first-child能替代p:first-of-type - 现代项目可直接放弃 IE8,但上线前务必查构建工具是否误启了旧版 Autoprefixer 配置,导致生成了无效回退代码
和 first-child 混用时样式被覆盖?检查层叠顺序
这两个伪类权重相同(都是单个伪类),谁在后面谁生效。比如写了 p:first-child { color: red; } 再写 p:first-of-type { color: blue; },那只要该 p 同时满足两个条件,最终颜色就是 blue。
- 不要假设
first-of-type“更精确” 就一定优先——CSS 层叠只看顺序和来源,不看语义强弱 - 调试时用浏览器开发者工具看“Computed”面板,确认到底是哪条规则生效,而不是凭感觉猜
- 若需强制区分,加一个无意义 class(如
.force-first-type)提高权重,比用!important更可控
真正容易被忽略的是:DOM 动态插入后,first-of-type 不会自动重新评估已渲染元素的匹配状态——它只在初始渲染和重排时计算。JS 插入新节点后,老的“首个”可能已不是首个,但样式不会自动更新,得手动触发重绘或改用 class 控制。










