后代选择器用空格、子选择器用>,区别在于中间能否插入其他元素;>要求父元素直接包含目标元素,空格则允许中间存在任意层级;DOM树中若目标元素非容器的直接子级,必须用空格。

后代选择器(空格)和子选择器(>)根本不是“深不深”的问题,而是“中间能不能插层”——能插,就用空格;不能插,就必须用 >。
怎么一眼判断该用 > 还是空格?
打开 DevTools,右键目标元素 →「Reveal in Elements panel」,直接看它在 DOM 树里挂在哪一级。如果父节点就是你写的那个容器,且中间没夹其他标签,> 安全;只要中间可能有 section、div、article 甚至文本节点,就得用空格。
-
.card > p只命中<div class="card"><p>...</p></div>里的p -
.card p会连<div class="card"><article><header><p>...</p></header></article></div>里的p一起抓 - 写
.nav > li却发现下拉菜单没样式?大概率二级li在<ul>里,已不是.nav的直接子级
.a > .b .c 和 .a .b > .c 完全是两回事
组合符的绑定优先级固定:> 总是紧贴左边选择器生效,空格则延续“后代”语义。这两个写法的匹配路径完全不同:
-
.a > .b .c= 先找.a的直接子.b,再在这个.b里找任意深度的.c -
.a .b > .c= 先找.a内任意位置的.b,再找这个.b的直接子.c - 误写成
.list li:not(.disabled)而不是.list > li:not(.disabled),很可能把嵌套菜单里的li也放进来,导致隐藏逻辑失效
性能差异真有那么大?
日常页面几乎感觉不到,但以下场景会暴露问题:
立即学习“前端免费学习笔记(深入)”;
- 长列表动态渲染(比如虚拟滚动区域),
.item p比.item > p多做几轮祖先链遍历,重绘卡顿更明显 - DOM 深度超过 5 层时,
div ul li a的匹配耗时显著高于nav > ul > li > a - 浏览器对
>的优化更成熟——它只查一层子节点,不用递归进子树
真正容易被忽略的,是结构契约:用 > 不是为了“快”,而是为了“翻车时能立刻发现 HTML 改动了”。一旦 DOM 嵌套变深,> 直接不生效,反而帮你守住样式和结构的边界;空格选择器则默默继续工作,直到某天某个 .title 在侧边栏里突然变色,你才意识到它早该被隔离。


















