.a.b 表示同一元素同时具备a和b两个类,是CSS交集选择器;.a .b 是后代选择器,匹配.a内部任意层级的.b元素;空格在HTML中分隔类名,在CSS中表示层级关系,二者语义不同且不可互换。

`.a.b` 是单元素交集,不是“省略空格”而是语法定义
`.a.b` 中的两个点号连写,不是“忘了加空格”,而是 CSS 选择器语法里明确规定的「类名合取(compound class selector)」:它要求目标元素的 class 属性中**同时包含 a 和 b 这两个独立类名**。浏览器解析时,会把 class="a b" 拆成字符串数组 ["a", "b"],再检查是否全部存在——顺序无关,空格位置无关,甚至中间多几个空格也无妨。
这个行为等价于属性选择器:[class~="a"][class~="b"](~= 表示空格分隔列表中的精确单词匹配)。所以它根本不是“没空格”,而是「空格在 HTML 属性里负责分隔类,在 CSS 选择器里连写点号才表示‘且’关系」——两边语义不互通,各管各的。
`.a .b` 的空格是选择器层级运算符,不是分隔符
`.a .b` 中的空格是 CSS 定义的「后代选择器(descendant combinator)」,它不作用于单个元素,而描述一种 DOM 层级关系:查找所有满足「某个 .b 元素,其任意祖先(不一定是父级)是 .a」的节点。
常见误判点:
立即学习“前端免费学习笔记(深入)”;
- 以为
.btn .primary是“给按钮加 primary 样式”,实际它会匹配<div class="btn"><p><span class="primary">文字</span></p></div>—— 样式落在span上,和button无关 - 在组件封装时写
.modal .header,结果用户加了个 wrapper div,.header就失效了,因为层级链断了 - 用 SCSS 的
& .icon(带空格),编译后变成.modal .icon,但你本意可能是.modal-icon
为什么不能统一用空格?浏览器解析规则不允许
CSS 选择器语法从 Level 1 就严格区分了这三类写法,浏览器引擎(Blink、WebKit、Gecko)按此解析,没有商量余地:
-
.a.b→ 单节点多类匹配(快,稳定,推荐用于状态组合) -
.a .b→ 跨节点后代查找(慢,依赖 DOM 结构,慎用) -
.a, .b→ 分组选择器(逗号分隔,表示“或”)
如果强行用空格替代连写,比如把 .input.error[disabled] 写成 .input .error [disabled],那它就变成「.input 内部的 .error 元素,再找它内部带 disabled 属性的子元素」——完全不是原意,而且很可能找不到。
调试时最该盯住 DevTools 里的匹配路径
Chrome 或 Firefox 的开发者工具里,选中元素后看右侧 Styles 面板顶部显示的实际生效选择器。如果看到的是 .parent .child,立刻确认:这个空格,是你真需要穿透嵌套,还是手抖多按了一次空格键?
真正难的不是记规则,是在每次敲下空格键前,心里清楚自己要的是「同一个元素上的多个身份」,还是「两个不同元素之间的位置关系」——前者连写,后者才加空格。


















