不该。通用交互修饰符如is-active应独立命名、全局可用,不绑定具体BEM组件,靠层级选择器限定作用域,避免破坏复用性与语义归属,同时防止样式冲突和DOM误操作。

通用交互修饰符该不该放在某个具体BEM组件下?
不该。把 is-active、is-open、is-disabled 这类状态修饰符硬塞进某个组件(比如 .menu__item--is-active)会破坏复用性,也违背 BEM “语义归属清晰” 的本意——这些状态不是 menu__item 独有的,按钮、卡片、折叠面板都可能需要。
推荐命名方式:用独立的、无上下文前缀的修饰符类名
直接使用 is-active、is-open、is-hidden 这类扁平命名,不带任何块名前缀。它们是全局可用的状态钩子,靠 CSS 优先级和 DOM 结构控制作用范围:
- 确保这些类在 CSS 中定义得足够早(比如放在基础重置之后、组件样式之前),避免被局部样式意外覆盖
- 不依赖
!important,而是靠结构化写法:比如.is-open .dropdown__panel控制展开时的子元素显示,而不是给.dropdown__panel单独加--is-open - 避免和组件内部的私有修饰符混淆:组件内仍可用
.button--primary这类带块名的修饰符表达设计变体,而is-前缀专用于运行时状态
为什么不用 u-is-active 或 js-is-active?
加 u-(utility)前缀容易让人误以为它是可单独使用的工具类(如 u-mt-8),但 is-active 本身不具备独立视觉效果,它必须配合其他规则生效;加 js- 则混淆了关注点——这个类名是给 CSS 用的,JS 只负责增删,命名不该暴露实现细节。
更实际的问题是:一旦加了前缀,团队成员会开始争论“这个 js-is-open 到底该由 JS 初始化还是由后端模板注入”,反而模糊了职责边界。保持 is- 纯语义、纯 CSS 面向,JS 只管 toggle,CSS 只管响应,协作更轻量。
立即学习“前端免费学习笔记(深入)”;
遇到多层嵌套状态时怎么避免冲突?
比如一个 .modal 内部有 .tabs,两者都需要 is-active,但激活逻辑不同。这时候不能靠类名区分,而要靠层级选择器限定作用域:
.is-active .modal__overlay { opacity: 1; }
.is-active .tabs__item { color: var(--accent); }
关键点在于:不要试图用 is-modal-active 和 is-tabs-active 拆分状态名,那会让 HTML 膨胀且难以维护。状态类名保持统一,靠 CSS 选择器路径做隔离——这也是 BEM 推荐的“用结构代替命名爆炸”的思路。
真正容易被忽略的是:这类修饰符一旦脱离 DOM 层级约束(比如被 JS 错误地加在了 body 上),就可能意外触发深层样式。所以建议所有 is- 相关规则都显式写出父级上下文,哪怕只是 .component-name.is-active,别裸写 .is-active。


















