:first-child匹配父元素的第一个子节点,无视标签类型;:first-of-type匹配同标签兄弟中首个出现的元素。二者在纯同标签结构中效果相同,但混排时行为迥异,且:first-child易受文本节点干扰。

first-child 只认位置,不认标签类型
:first-child 判断的是某个元素是否是其父容器的**第一个子节点**,完全不管它是什么标签、什么类型。哪怕前面有注释、文本节点(比如空格换行),或者 <div> 前面插了个 <span>,只要它不是第一个,就匹配不上。
常见错误现象:<ul><li>A</li><li>B</li></ul> 中的 <li>A</li> 能被 li:first-child 选中;但若写成 <ul><span>hint</span><li>A</li><li>B</li></ul>,li:first-child 就失效了——因为 <li> 已经不是第一个子元素。
实操建议:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 用
:first-child时,确保目标元素在 DOM 树中**严格处于子节点序列首位** - 调试时可打开浏览器开发者工具,右键检查父元素 → 查看「Elements」面板里的子节点顺序(含文本节点)
- 避免依赖 HTML 源码缩进或换行,它们会生成空文本节点,影响匹配
first-of-type 只认标签名,不认位置
:first-of-type 匹配的是:在所有同名兄弟元素中,**出现顺序最早的那一个**。它会跳过其他类型的兄弟节点,只在同标签中排序。
立即学习“前端免费学习笔记(深入)”;
使用场景:父容器里混排了多种元素,但你想精准定位某类标签的第一个实例。比如 <article><p>intro</p><h2>title</h2><p>content</p></article> 中,p:first-of-type 会命中第一个 <p>,即使它不是整个 <article> 的第一个子元素。
实操建议:
-
h2:first-of-type在多个<h2>并存时,总能选中第一个,不管前面有没有<p>或<div> - 注意“同类型”指**相同标签名 + 相同命名空间**(比如 SVG 中的
<circle>和 HTML 中的<circle>不算同类) - 它对自定义元素也有效,
my-button:first-of-type会匹配同级中第一个<my-button>
为什么 div:first-child 和 div:first-of-type 结果经常一样?
当父容器下所有子元素都是 <div> 时,二者效果重合——第一个 <div> 既是第一个子元素,也是第一个 <div> 类型元素。
但只要插入一个不同标签,差异立刻暴露:
<section> <header>Top</header> <div class="item">1</div> <div class="item">2</div> </section>
此时:
-
div:first-child→ 不匹配(<div>是第二个子元素) -
div:first-of-type→ 匹配第一个<div class="item">
性能上无显著差异,两者都是 CSS 选择器引擎的常规匹配逻辑,但 :first-of-type 需要遍历同名兄弟节点,理论上略多一次类型过滤。
容易被忽略的边界情况
这两个伪类都不匹配动态插入的元素(除非重新触发样式计算),也不受 display: none 影响——隐藏的元素仍参与计数。
关键陷阱:
- HTML 中的换行和空格会被解析为文本节点,可能让
:first-child失效,而:first-of-type不受影响 -
:first-child对<template>内容无效(内容未渲染,不在活跃 DOM 树中) - 在 Shadow DOM 中,它们只作用于各自作用域内的子树,不会跨影子边界
- 没有
:last-of-type这种原生选择器,别想当然类推
真正需要“首个特定类型”时,优先用 :first-of-type;只有当你明确要求“就是第一个子元素”,且能控制 HTML 结构干净无空白时,才考虑 :first-child。

















