bem不可妥协的三条底线是:块作用域隔离、元素不跨块、修饰符不带具体值;其余细节可依团队协作成本动态调整。

不需要全盘接受,BEM 是一套可裁剪的约束体系,关键在守住三条底线:块作用域隔离、元素不跨块、修饰符不带具体值。其余细节(比如要不要写 __header 还是 __title)应按团队实际协作成本动态取舍。
哪些BEM规则不能妥协
这三条一旦松动,BEM 就退化成“带下划线的普通 CSS”,冲突和维护成本会指数级上升:
-
Block 必须有业务语义且唯一:比如
user-profile✅,profile❌,container❌。泛义名在第 3 个迭代必撞车 -
Element 只能直属于 Block,且不能脱离 Block 单独使用:HTML 中必须同时出现
user-profile和user-profile__avatar,否则删掉 Block 类整个样式就崩 -
Modifier 名必须描述可枚举状态,禁用含具体值的写法:比如
button--disabled✅,button--w-200px❌;card--stacked✅,card--top-16❌
哪些BEM细节可以灵活调整
这些点不影响核心隔离能力,强行统一反而拖慢开发节奏:
-
双下划线
__和单中划线-的混用:只要工具链(如stylelint-selector-bem-pattern)能识别并校验结构,user-profile__avatar和user-profile-avatar在构建后效果一致,前者更标准,后者在快速原型阶段可接受 -
是否强制所有 Element 都显式声明:比如
user-profile__bio和user-profile__bio-text,如果bio永远只有一层文本内容,user-profile__bio足够,不必硬拆 -
修饰符组合方式:
button--primary--large和button--primary button--large渲染效果相同,后者更利于 JS 动态增删,前者更紧凑——选哪个取决于团队对 className 拼接的偏好(推荐用clsx统一处理)
为什么“全盘接受”反而容易翻车
真实项目里最常卡住团队的不是 BEM 规则本身,而是工具链没跟上:
-
没配 Stylelint 或设为 warning 级别:Sass 里写了
.user-card { & .user-card__badge { } },编译出带空格的选择器.user-card .user-card__badge,没人发现,直到 DOM 结构微调后样式集体失效 -
没约束 CSS 引入顺序:两个文件都定义了
.button--primary,谁后加载谁生效——BEM 不解决层叠顺序问题,但很多人误以为它能 -
把 BEM 当命名格式,忽略 Block 语义:写
section-2__title,结果重构时删了 section-2,整个标题样式消失,因为名字没绑定业务含义
真正要盯死的是构建产物里有没有空格选择器、有没有同名类被不同模块重复定义、Modifier 是否在模板里被随意拼写——这些才是让 BEM 失效的临界点,不是某个下划线少写了一条。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











