BEM不是补救CSS Modules混乱的工具,而是与其配合的结构层规范;CSS Modules解决全局污染,BEM解决语义组织,二者叠加才能既防冲突又保可读。

直接上结论:BEM 不是用来“补救” CSS Modules 命名混乱的,而是和它配合使用的结构层规范。CSS Modules 解决的是类名全局污染问题,BEM 解决的是语义组织问题;两者叠加,才能既不冲突、又可读。
为什么开了 CSS Modules 还要写 BEM 类名
CSS Modules 会把 .button 编译成类似 _button_abc123 的哈希名,确实避免了冲突,但代价是原始类名丢失语义 —— 你在 DevTools 里看到的是一堆随机字符串,没法一眼识别组件结构或复用意图。
- 只靠 CSS Modules,
Button.module.css和Card.module.css都可能有.title,编译后不冲突,但没人知道哪个title属于哪个组件 - BEM 类名(如
button__label)保留在开发时的源码中,既是开发者协作语言,也是调试线索 - 构建后,CSS Modules 仍会对
button__label做哈希处理,不影响封装性
在 CSS Modules 文件里怎么写 BEM 类名
直接写,别省略前缀。BEM 是命名约定,不是语法限制 —— 它和是否启用模块化完全正交。
- ✅ 正确:
.button { }、.button__icon { }、.button--primary { } - ❌ 错误:
.icon { }(脱离 block,失去上下文)、.button .icon { }(类型选择器,破坏封装) - 注意:BEM 修饰符(
--)不能用在嵌套规则里,比如 Sass 中不要写.button { &--primary { ... } },应平级定义
React 组件里怎么安全地组合 BEM + CSS Modules
关键不是拼字符串,而是让 BEM 结构在 JSX 中清晰可维护。
立即学习“前端免费学习笔记(深入)”;
- 用
clsx或classnames动态组合:className={clsx(styles.button, styles['button--primary'], hasIcon && styles['button__icon'])} - 禁止在 JSX 中硬编码哈希后的类名(如
className="_button_abc123"),那等于放弃 CSS Modules 的可维护性 - 如果用了 Tailwind,BEM 类名只用于结构标识(如
user-card),视觉细节交给tw`text-lg font-medium`,二者不混写逻辑
最容易被忽略的一点:BEM 不是给机器看的,是给人看的
很多团队开了 CSS Modules 就以为万事大吉,结果组件目录里全是 styles.css、index.module.scss,连文件名都看不出对应哪个 UI 元素。BEM 的真正价值,是在文件命名、目录结构、类名三者之间建立一致映射 —— 比如 components/Button/Button.module.css 里只允许出现 button、button__*、button--* 开头的类名。一旦打破这个约束,再好的工具也救不了语义断层。


















