正确语法是多个类名连写不加空格,如.btn.primary.large,表示同一元素同时具备这三个类;空格表示后代关系,逗号表示分组匹配,顺序无关但必须全部存在于class属性中。

多个类名连写才是“同时具备”的正确语法
想选中一个元素必须同时拥有 .btn、.primary、.large 三个类,就写 .btn.primary.large——中间**不能有空格**,每个类前都带点。浏览器会检查该元素的 class 属性值是否包含全部这三个词(以空格分隔),顺序无关。
常见错误现象:.btn .primary 看起来像“两个类”,实际是后代选择器,会去找 .btn 元素内部任意层级的 .primary 元素;.btn, .primary 是分组选择器,匹配任一满足的元素,不是交集。
-
class="btn primary large"→ 能被.btn.primary.large匹配 -
class="primary btn large"→ 同样能匹配(顺序无关) -
class="btn-primary large"→ 不匹配(btn-primary是一个整体类名) -
class="btn,primary,large"或class="btn;primary;large"→ 完全不生效(HTML 中 class 值只认空格分隔)
和属性/伪类混用时,把它们放在末尾
交互态或状态约束要加在链式类选择器的最后,比如 .btn.danger:hover 或 .input.error[disabled]。虽然浏览器能解析 .btn:hover.danger,但语义混乱,容易误读为“hover 后再加 danger 类”。
注意布尔属性如 disabled 只对原生表单控件有效,对 div 加 disabled 属性不会触发 [disabled] 匹配。
立即学习“前端免费学习笔记(深入)”;
- 推荐:
.card.is-active:hover、button.cta[disabled] - 不推荐:
.card:hover.is-active(可读性差)、div.cta[disabled](无效) - 伪类和属性选择器本身不提升特异性权重,但会参与匹配逻辑
别为了提权硬凑三四个类连写
写 .btn.primary.large.disabled.loading 表面上更“精准”,实则脆弱:JS 动态删掉其中任一类,整条规则就失效。真正需要的是清晰的状态分离。
性能上没问题,现代浏览器解析毫无压力;但维护成本高,且和 BEM、原子 CSS 等主流实践冲突。
- 更健壮的做法:
.btn做基础样式,.btn.loading单独覆盖加载态 - Vue/React 中用
:class="{ 'btn': true, 'loading': isLoading }",确保 CSS 规则只依赖稳定存在的基础类 - IE8 及更早版本不支持多类连写(只认第一个类),如需兼容,得用单类或 JS 补丁
调试时先看 computed styles 里的 class 列表
规则没生效?打开开发者工具,直接看目标元素的 Computed 标签页里显示的 class 属性值——是不是真包含了你写的每一个类?有没有拼错、多空格、动态渲染漏加?
框架生成的 class 名容易被压缩或作用域隔离(如 Vue scoped style),PostCSS 插件也可能重命名,最终输出的 class 字符串和你写的 CSS 选择器不一致,这是比语法错误更隐蔽的问题。
真正难的不是怎么写,而是判断哪些类该组合、哪些该独立;以及 HTML、JS、CSS 三端的 class 名是否始终对齐。


















