:only-child不可靠,因它检查childNodes.length===1(含文本、注释节点),换行或注释即失效;应改用children.length===1或:only-of-type。

:only-child 不能可靠判断“容器中是否只有一个元素”——它判断的是「父元素的 childNodes.length === 1」,而这个长度包含所有文本节点、注释节点,哪怕一个换行符都会让它失效。
为什么 document.querySelector('div:only-child') 经常返回 null?
不是选择器写错了,是 DOM 结构根本没满足条件:
-
div标签里写了一行换行:<div>\n <p>内容</p>\n</div>→childNodes.length至少为 3(两个 #text + 一个p) - Vue 模板中用了
v-if,编译后留下 HTML 注释节点<!--v-if--> - React 中用了
<>...</>Fragment,虽然不渲染,但会插入空文本节点 - CMS 或富文本编辑器输出的内容自带不可控空白和换行
真正想判断“只有一个元素”,该用 children.length
children 只统计元素节点(Element),自动过滤掉文本、注释等干扰项。这才是前端日常要的真实逻辑:
- 检查是否只剩一个
p:document.querySelector('.container').children.length === 1 - 检查是否只剩一个
li:ul.children.length === 1 - JS 动态加 class:
if (parent.children.length === 1) parent.classList.add('single'),再写.single > *样式
:only-of-type 才是你多数时候真正需要的
90% 场景下,你要的不是「整个父容器只许有一个子节点」,而是「同类型里只有一份」:
立即学习“前端免费学习笔记(深入)”;
-
li:only-of-type在<ul><li>A</li><p>说明</p></ul>中依然命中 -
p:only-of-type能安全用于用户粘贴的富文本,无视中间有多少空格或换行 -
:has(> *:only-of-type)可触发容器级样式(Chrome 105+ / Firefox 121+ 支持,Safari 当前不支持)
别在控制台反复试 :only-child 是否生效——先查 parentNode.childNodes.length。眼睛看到的“空”,DOM 里往往全是节点。


















