BEM官方推荐使用--active,is-active是社区衍生的布尔型类名,并非BEM原生语法;它易与JS类名混淆且易被构建工具误删,应统一用--修饰符保持命名一致性。

布尔型修饰符该用 is-active 还是 --active
BEM 官方规范只定义了 --modifier 这一种修饰符写法,is-active 是社区衍生的“布尔型状态类”,不是 BEM 原生语法。它常被用于 JS 瞬时控制(比如 classList.toggle('is-active')),但容易和真实修饰符混淆:浏览器不认语义,只认 DOM 中是否真实存在 class;而 is-active 一旦漏加、拼错或被 PurgeCSS 误删,样式就彻底失效。
实操建议:
- 统一用
--active,和--disabled、--loading保持命名体系一致 - 若必须用
is-前缀(如框架约束或历史代码),仅限纯 JS 行为开关,且 CSS 中不依赖它做核心样式(例如禁用态仍需button--disabled控制pointer-events) - 检查 DevTools 的 Elements 面板,确认目标元素的
class属性里真有tab__item--active,而不是tab__item is-active混用
button--disabled 加上了却没反应,问题通常不在 BEM
根本原因几乎总是:类名没真正写进 DOM,或者写了但被覆盖/误删。BEM 不执行逻辑,它只提供命名契约;浏览器只响应真实存在的 class 字符串。
常见错误现象与对应检查点:
立即学习“前端免费学习笔记(深入)”;
-
element.className = 'button--disabled'—— 错!会清空其他 class;应改用element.classList.add('button--disabled') - React/Vue 中 state 更新了,但 class 绑定没同步(例如写了
isDisabled却忘了映射到className或)</li> <li>构建工具(如 PurgeCSS)把动态添加的修饰符当“未使用”删掉了,需在 <code>safelist
中显式保留/button--(disabled|loading)/ - CSS 规则写错:比如写了
.button--disabled { opacity: 0.5; },但实际需要同时禁用交互,漏了pointer-events: none
多个布尔修饰符共存时怎么写才不冲突
BEM 允许多修饰符并列,比如 button--primary button--loading button--disabled,但前提是它们语义正交、CSS 规则互不覆盖。
关键实操原则:
- 避免组合选择器:
.button--primary.button--loading权重高、难调试、漏一个类就失效;应拆成独立规则:.button--primary控颜色,.button--loading控光标和动画 - 叠加状态需显式处理:
.button--disabled.button--loading { opacity: 0.6; },不能指望两个修饰符自动合并效果 - 禁止嵌套写法:
button--primary-loading是非法的——它不再是修饰符,而是新块名,破坏 BEM 可预测性 - 顺序不影响渲染,但建议按「类型 → 状态 → 尺寸」排列,提升可读性:
button--primary button--loading button--large
为什么不能把修饰符直接挂在 Block 上,比如 button--disabled
因为 BEM 要求修饰符必须依附于具体节点,脱离上下文就失去语义锚点。button--disabled 看似简洁,但 button 可能复用于不同场景(表单提交按钮 vs 工具栏图标按钮),这个修饰符到底禁用的是点击?焦点?还是整个组件生命周期?没人能确定。
更可控的做法:
- 绑定到明确子元素:
button__trigger--disabled(表示触发区域不可点),button__icon--hidden(图标隐藏) - 避免泛化命名:
button--size-large合规,button--big不合规(big 是主观形容词,无基准) - 若真需表达块级状态,优先用键值型修饰符:
button--state-disabled,比布尔型更易扩展(后续可加--state-pending)
最常被忽略的一点:修饰符不是开关,它是 DOM 状态的快照。JS 必须真实更新 class,CSS 必须严格按命名书写,DevTools 必须验证两者是否对齐——三者缺一,BEM 就只是名字而已。


















