:empty仅匹配无任何子节点(含文本、空格、换行、注释)且无伪元素内容的元素;它纯结构判断,不感知display:none或动态内容,无法替代JS视觉判空。

直接用 :empty 就行,但要注意它只匹配「完全没内容」的元素——连空格、换行、注释都不行。
什么是 :empty 认为的“空”?
:empty 只匹配那些既没有子节点(包括文本节点),也没有伪元素(如 ::before/::after)生成内容的元素。哪怕有一个空格或回车,就不是空。
- ✅
<div></div>—— 匹配 - ❌
<div> </div>—— 不匹配(有空格) - ❌
<div>\n</div>—— 不匹配(有换行符) - ❌
<div><span></span></div>—— 不匹配(有子元素) - ❌
<div></div>+div::before { content: "" }—— 不匹配(伪元素生成了内容)
:empty 不能替代 JS 判断内容是否为空
它无法感知动态插入的内容变化,也不能识别 display: none 子元素是否隐藏了内容。比如:
div {
background: #eee;
}
div:empty {
background: red;
}
<div><span style="display:none">text</span></div>
这段 HTML 中,<div> 实际上不为空(有子节点),所以 <code>:empty 不生效 —— 即使那个 <span></span> 被隐藏了。
立即学习“前端免费学习笔记(深入)”;
- 想判断“视觉上为空”,得用 JS 检查
element.innerText.trim() === '' -
:empty是纯结构判断,和渲染无关 - 服务端渲染时若模板里留了空格,也容易踩坑
常见误用:想给“无文字但有图标”的容器设样式
比如按钮里只有 <svg></svg>,没有文字,但你希望它变窄一点:
<button><svg>...</svg></button>
这个 <button></button> 不是 :empty,因为 <svg></svg> 是子元素。这时候应该用属性选择器或类名区分:
- 加 class:
<button class="icon-only">...</button> - 用属性:
button:has(svg):not(:has(span, p, [class*="text"]))(需浏览器支持:has()) - 别硬套
:empty,它真不适用
真正要靠 :empty 的场景其实很窄:表单校验提示、动态列表项占位、服务端生成的纯骨架结构。用之前先 console.log(element.childNodes) 看一眼 DOM 树,比猜靠谱得多。


















