:first-child匹配父元素下序号为1且标签类型相符的子元素;:nth-of-type(1)和:first-of-type只按同标签序次匹配,无视其他节点;属性选择器结合:not()与~可精准定位首个带特定属性的元素。

用 :first-child 选中父容器下的第一个子元素
这个伪类匹配的是「其父元素下序号为 1 的子元素」,但前提是该元素必须是对应标签类型。比如 div:first-child 只会选中那些既是 div、又恰好排在父元素第一个位置的元素。
常见误判场景:
- 父元素第一个子是
p,后面才是div→div:first-child完全不生效 - 想选列表中第一个
li,但ul开头有注释或空文本节点 → 实际第一个子不是li,li:first-child失效
实操建议:
用 :nth-of-type(1) 选中同类型中的第一个元素
它不看整体顺序,只看「同种标签在父元素中出现的次序」。比如 p:nth-of-type(1) 会选中父元素里第一个 p 标签,不管前面有没有 div 或 span。
立即学习“前端免费学习笔记(深入)”;
适用场景:
- 文章段落中只想给第一个
p加顶部边距 - 表格中仅对第一列的
td设置背景色(配合td:nth-of-type(1))
注意点:
-
:nth-of-type只认标签名,不认 class 或属性,.item:nth-of-type(1)是无效写法 - IE8 不支持,需兼容旧环境时避免使用
用 :first-of-type 是 :nth-of-type(1) 的简写形式
功能完全等价,语义更直观,可读性略高。但两者编译后行为一致,选哪个纯看团队习惯。
示例对比:
ul > li:first-of-type { color: red; }
ul > li:nth-of-type(1) { color: red; }
二者效果相同,都只影响第一个 li,无论前面是否有 header 或注释节点。
小提醒:
- 不要和
:only-of-type混淆——后者要求该类型在整个父元素中唯一存在 - 若目标元素是动态插入的(如 JS 渲染),需确认插入时机是否影响选择器匹配
用属性选择器 + :not() 组合规避干扰节点
当 HTML 结构不可控(例如 CMS 输出带冗余节点),又必须精准定位第一个目标元素时,可以换思路:先排除非目标节点,再取第一个。
例如,要选第一个带 data-role="item" 的元素:
[data-role="item"]:not([data-role="item"] ~ [data-role="item"]) { opacity: 1; }
原理是利用「兄弟选择器 ~」排除所有后面还有同类兄弟的元素,只剩第一个。
这个技巧较冷门,但适合以下情况:
- 无法修改 HTML 结构,又不能依赖 JS
- 需要 CSS-only 解决方案且目标有稳定属性标识
- 其他伪类因 DOM 干扰失效时的备选路径
性能上无明显问题,但可维护性偏低,建议只在确实没别的办法时用。
真正容易被忽略的是:CSS 选择器永远基于当前 DOM 快照匹配,没有“首次渲染”或“初始状态”的概念。如果元素是异步加载或条件渲染的,得确认样式规则注入时机是否早于节点挂载。










