按钮禁用状态必须用 .btn--disabled,禁用/加载/幽灵等修饰符需正交组合、显式覆盖,禁止嵌套如 .btn--ghost--disabled,所有状态样式须通过 BEM 修饰符统一控制。

按钮禁用状态必须用 .btn--disabled,不能漏掉双连字符
直接写 .btn-disabled 或 .btn_disabled 会导致 BEM 语义断裂——它不再是“按钮的禁用状态”,而被解析成一个新块或普通类名。构建工具可能截断 --(如 css-loader 配置不当),DevTools 里也看不到状态上下文。基础样式 .btn 必须与修饰符共存:class="btn btn--disabled",否则 padding、display 等会丢失,按钮“看起来没变”其实是样式断层。
.btn--loading 要作用于整个按钮,别塞进子元素
加载状态是按钮整体的临时行为,不是图标或文字的私有属性。常见错误是加个 btn__loader 子节点,结果 button:disabled 不会停掉它的动画,也无法响应按钮尺寸变化。正确做法是:用 .btn--loading 控制光标、透明度、文字替换和 SVG 动画,所有样式通过该修饰符统一收口。SVG 图标建议用 currentColor 和 CSS 变量适配禁用/加载态颜色。
幽灵按钮(.btn--ghost)和禁用/加载状态可以叠加,但 CSS 必须显式处理组合
BEM 允许 .btn--ghost.btn--disabled 同时存在,但不会自动合并效果。比如 .btn--ghost 设了 border: 1px solid currentColor,.btn--disabled 设了 opacity: 0.6,两者权重相同,最终表现取决于 CSS 文件中哪条规则写在后面。容易踩的坑是只写单个修饰符规则,没覆盖组合场景:
.btn--ghost.btn--disabled {
opacity: 0.4;
cursor: not-allowed;
}
多个状态共存时,JS 添加类要用 element.classList.toggle('btn--disabled', isDisabled),避免字符串拼接漏空格或覆盖其他类。
立即学习“前端免费学习笔记(深入)”;
禁止嵌套修饰符,比如 .btn--ghost--disabled
这种写法在 BEM 中非法,它会被识别为一个新块名 btn--ghost--disabled,而非两个正交状态。语义上模糊:是“幽灵风格的禁用按钮”,还是“禁用的幽灵按钮”?更关键的是,它无法被 JS 动态切换——你得同时增删两个状态,逻辑耦合。真正需要控制的是“幽灵”和“禁用”这两个独立维度,它们应自由组合、互不干扰。如果某次需求要求幽灵按钮加载时不显示边框,就得单独写:.btn--ghost.btn--loading { border: none; },而不是靠命名猜意图。


















