CSS组合选择器分两类:分组选择器(逗号分隔,表示“或”关系,用于复用样式)和组合选择器(空格、>、+、~,表达DOM结构关系)。

“CSS 组合选择器”不是一种单一选择器,而是两类完全不同的东西——你得先分清是「分组(grouping)」还是「组合(combinator)」,否则一写就错、一调就懵。
分组选择器:用逗号写的“或关系”,本质是代码减冗手段
它解决的是“多个不同选择器要应用同一套样式”这个高频场景,核心是避免重复写规则块。
- ✅ 正确写法:
.header, .nav, .footer { color: #333; }—— 匹配所有.header元素 或 所有.nav元素 或 所有.footer元素 - ❌ 错误理解:以为
.a, .b是“同时满足 .a 和 .b”,其实它不表达交集,只表达并集 - ⚠️ IE8 兼容注意:逗号前后加空格没问题,但
.a ,.b(逗号后紧贴点)在旧版 IE 中可能解析失败 - ? 混合类型也支持:
#main, [type="submit"], .btn-primary—— ID、属性、类三者任一匹配即生效
组合选择器(Combinators):用空格/>/+/~写的“结构关系”,控制层级与顺序
这类选择器不是为了省代码,而是精准定位 DOM 结构中的相对位置。四种符号语义完全不同,不能互换:
-
(空格):后代选择器 →.article p匹配.article内任意嵌套深度的p -
>:子元素选择器 →.article > p只匹配.article的**直接子级**p,跳过孙子辈 -
+:相邻兄弟选择器 →h2 + p只匹配紧跟在h2后面、同父级的**第一个**p -
~:通用兄弟选择器 →h2 ~ p匹配h2同父级下**所有后续**的p,不管中间隔了几个其他标签 - ⚠️ 常见误用:
.list li:first-child看似合理,但如果.list里还有div、span等非li子项,:first-child就可能失效——此时应改用:first-of-type或更稳妥的 BEM 命名 + 类控制
伪类+组合混用:状态与结构叠加时的优先级和可读性陷阱
比如想给“导航栏中处于 hover 态的链接”加下划线,写成 .nav a:hover 没问题;但一旦链式变长,就容易失控:
立即学习“前端免费学习笔记(深入)”;
- ❌ 危险写法:
a:hover:active:focus:not([disabled])—— 语义混乱、难以维护、部分浏览器对伪类叠加顺序敏感 - ✅ 推荐拆解:
a.nav-link:hover:not(:disabled)+ 单独定义a.nav-link:active,用类名锚定作用域 - ? 新语法辅助:
:is(:hover, :focus-visible)可收拢多状态,但需检查目标浏览器是否支持(Chrome 105+/Firefox 109+ 支持良好) - ⚠️ 特别注意:
input:required:focus比input:focus优先级高,但若同时存在.form-input:focus(类选择器),后者会赢——因为类选择器权重大于伪类
真正难的不是记住符号,而是在写 .card .title 还是 .card > .title 时,能立刻判断出设计稿里那个标题是不是永远只做一级子元素;也不是要不要用 [data-status="error"],而是当后端突然返回 data-status="ERROR"(全大写)时,你有没有提前加 i 标志符:[data-status="error" i]。










