bem是主干命名规范,非bem类名仅允许三类:基础重置类(如visually-hidden)、工具类(如mt-4)、第三方库原始类(如ant-btn),且须物理隔离与工具拦截,否则破坏隔离性。

不应该完全禁止,但必须明确边界:BEM 是主干命名规范,非 BEM 类名只能出现在严格受限的场景,否则会立刻破坏隔离性、引发样式泄漏。
哪些非BEM类名是允许存在的
不是所有类名都得套 BEM,关键看它是否承担「结构归属」或「状态表达」职责:
-
reset.css或base.css中的基础重置类(如visually-hidden、sr-only)——它们不归属任何 block,属于跨项目通用原子类 - 工具类(utility classes),比如
mt-4、text-center,前提是项目已约定并统一管理(如用 Tailwind 或自建原子 CSS 系统) - 第三方库的原始类名(如
ant-btn、el-input),你不能改,但要用 wrapper block 隔离,而不是在自己 CSS 里写.ant-btn直接覆盖 - JS 用于 DOM 操作的标记类(如
js-toggle-menu),这类纯行为类不参与样式渲染,只供 JS 查询
为什么直接写 .btn-primary 就算违规
它看起来像“按钮主要样式”,但缺失 block 归属,导致三类问题:
- 无法判断这个
btn-primary属于哪个组件上下文——是modal__button还是form__submit?一旦两个模块都用,样式就互相干扰 - 构建工具(如 stylelint-selector-bem-pattern)无法识别它是否合规,CI 里拦不住,等上线才发现冲突
- 开发者看到
btn-primary会下意识复用,结果改一个圆角,三个不同卡片里的按钮全变,却查不到源头
非BEM类名最容易被误用的三个地方
这些地方看似合理,实则埋雷:
- SCSS 中用
&--loading生成.button--loading✅,但写成&.is-loading→ 生成.button.is-loading❌,双类名违反 BEM 单一职责,且is-loading不带 block 前缀,无法追溯归属 - React 组件里传入
className="custom-style"作为 prop fallback —— 如果这个custom-style是项目内定义的,就必须是完整 BEM 全称(如card__header--custom),不能是泛义缩写 - 写媒体查询时加
.mobile-layout类——BEM 不处理响应式逻辑,应改为给 layout 加layout--sidebar-collapsed这类语义化状态,由容器控制,而非引入新命名空间
如何让非BEM类名不污染 BEM 体系
核心是「物理隔离 + 工具拦截」:
- 把原子类、工具类、JS 标记类全部收进单独目录(如
src/styles/utils/),禁止在blocks/或components/下新建同类型类名 - stylelint 配置中启用
selector-max-specificity: "0,1,0",自动报错所有.foo .bar或#id .class写法,防止非 BEM 类名被嵌套滥用 - Git hooks 或 CI 中跑
npx stylelint "**/*.{css,scss}" --ignore-path .stylelintignore,把utils/目录加入 ignore,但确保blocks/和components/下 100% 无例外
真正难的不是记住哪些能用、哪些不能用,而是当有人提 PR 加了个 .highlight-text 类时,你能立刻判断它该归入 utils 还是该拆成 article__text--highlighted——这取决于它是否绑定具体 block 的语义。没归属,就不该进样式主干。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











