bem官方只定义--modifier一种修饰符语法,is-active是社区衍生的状态类,非bem原生;它脱离上下文、易被误删、难调试,应统一用tab__item--active等绑定元素的--修饰符表达状态。

is-active 不是 BEM 修饰符,它是独立的状态类名体系
BEM 规范只定义了 --modifier 这一种修饰符语法,is-active 属于社区自发形成的“状态类”命名习惯,并非 BEM 原生组成部分。它不绑定任何块或元素上下文,语义上等同于 .active,只是加了前缀避免全局冲突——但这也恰恰带来问题:浏览器无法区分 is-active 是 JS 行为开关还是样式锚点。
常见错误现象:
- 在 React 中写
className={isTabActive ? 'tab__item is-active' : 'tab__item'},结果 CSS 里却只写了.tab__item--active,导致样式不生效 - 用
classList.toggle('is-active')切换,但对应样式规则写成.tab__item.is-active,而没覆盖所有可能的父级组合(如.tab--vertical .tab__item.is-active) - PurgeCSS 把
is-active当作未使用类删掉,因为 HTML 模板里没硬编码它
tab__item--active 才是 BEM 正确的状态表达方式
当你要表达「某个 tab 项当前被选中」,应该用 tab__item--active,而不是 tab__item is-active。前者明确归属、可预测、可静态分析;后者脱离上下文,容易误删、难调试、无法体现组件边界。
实操建议:
- 所有视觉状态(选中、禁用、加载中、错误)统一走
--修饰符,如button--disabled、input--error、tab__panel--hidden - 如果框架强制要求
is-前缀(比如某些 UI 库的 props 映射),仅把它当作 JS 控制信号,CSS 样式仍由对应 BEM 修饰符承担,例如:isDisabled={true}→ 触发添加button--disabled,而非依赖is-disabled - 检查 DevTools 的 Elements 面板,确认 class 属性里真实存在的是
tab__item--active,不是tab__item is-active拼接或空格分隔
为什么混用 is-active 和 --active 容易出 bug
根本矛盾在于:BEM 是命名契约,is-active 是行为标记,二者职责不同却常被当成等价物使用。一旦混用,就会出现样式断层。
典型问题场景:
- CSS 选择器写成
.tab__item.is-active,但 DOM 中实际是class="tab__item tab__item--active"→ 样式不匹配 - 构建工具(如 PurgeCSS)配置了
safelist: [/^is-/],但漏掉了动态生成的tab__item--active→ 构建后丢失关键样式 - 多人协作时,A 写 JS 用
is-active控制,B 写 CSS 只写了tab__item--active→ 功能上线即失效 - 组件复用时,
is-active被带到新上下文中,但没有对应样式规则(如.card__header.is-active从未定义)→ 状态不可见
什么时候可以保留 is-active
仅限两种情况:纯 JS 行为标记,且不参与核心样式控制。
例如:
- 为屏幕阅读器添加临时焦点状态:
element.classList.add('is-focused'),CSS 中仅用它配合aria-*属性做辅助,主视觉样式仍由input--focused实现 - 动画触发钩子:
transitionend后加is-animating-out,用于 JS 监听并清理 DOM,不写任何 CSS 规则 - 历史项目迁移过渡期,旧代码大量使用
is-,可先用 PostCSS 插件自动补全对应 BEM 类(如把is-active替换为tab__item--active),再逐步收敛
真正难处理的从来不是怎么写类名,而是让所有人对「这个类名到底谁负责、在哪生效、删了会怎样」有同一认知。BEM 的 -- 修饰符天然携带上下文,is- 类没有——这点一旦忽略,后续排查成本会指数级上升。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











