CSS组合选择器分两类:分组选择器(逗号分隔,表示“或”关系,用于复用样式)和组合选择器(空格、>、+、~,表达DOM结构关系)。
“CSS 组合选择器”不是一种单一选择器,而是两类完全不同的东西——你得先分清是「分组(grouping)」还是「组合(combinator)」,否则一写就错、一调就懵。
它解决的是“多个不同选择器要应用同一套样式”这个高频场景,核心是避免重复写规则块。
.header, .nav, .footer { color: #333; } —— 匹配所有 .header 元素 或 所有 .nav 元素 或 所有 .footer 元素.a, .b 是“同时满足 .a 和 .b”,其实它不表达交集,只表达并集.a ,.b(逗号后紧贴点)在旧版 IE 中可能解析失败#main, [type="submit"], .btn-primary —— ID、属性、类三者任一匹配即生效这类选择器不是为了省代码,而是精准定位 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]。
来电咨询