bem 与 sass 嵌套冲突因后者生成层级选择器(如 .card .card__title),而 bem 要求扁平化(.card__title);应禁用普通嵌套,仅用 &__element / &--modifier,状态用修饰符而非伪类,变量与类名解耦,块名全局唯一并加前缀。

为什么直接用 BEM 命名但 Sass 嵌套后类名还是乱?
因为 Sass 的嵌套会生成层级选择器(比如 .card .card__title),而 BEM 要求所有修饰符和元素都挂载在块名下、扁平化输出(.card__title)。嵌套写法和 BEM 原则天然冲突,不加约束就会产出冗余、不可预测的选择器。
实操建议:
- 只对
&用法做严格限制:在块级选择器内,用&__element或&--modifier显式拼接,禁用多层普通嵌套(如.card { .title { ... } }) - 把组件拆成独立
_card.scss文件,根选择器必须是块名(.card),内部只允许出现&__xxx和&--xxx - 用
@at-root提前跳出嵌套处理伪类或媒体查询,避免生成.card:hover .card__btn这类非 BEM 结构
怎么让 hover / disabled 这类状态不破坏 BEM 结构?
BEM 规定状态应作为修饰符(&--disabled)出现在块或元素上,而不是靠父级状态推导。否则会导致样式依赖 DOM 层级,复用性和可测试性下降。
实操建议:
- 状态类必须手动加到 HTML 元素上,例如
<button class="btn btn--disabled"></button>,而非靠.btn:disabled或.btn-wrapper--disabled .btn - 在 Sass 中统一用
&--hover、&--focused等命名,配合 JavaScript 控制类名切换;避免写&:hover直接作用于块名(这会丢失响应式或 JS 控制能力) - 如果必须保留伪类逻辑(比如按钮默认悬停态),用
@at-root单独提一层:.btn { &__icon { @at-root .btn--hover & { transform: scale(1.1); } } }
Sass 变量和 BEM 块名重复定义,怎么避免维护两套命名?
常见错误是分别定义 $button-color 和 .btn,结果改了变量名却忘了同步 CSS 类,或者反过来。本质是把「样式配置」和「结构标识」混在了一起。
实操建议:
- 变量只管设计系统维度(颜色、间距、断点),不带组件语义,例如
$color-primary、$space-md;BEM 类名只管结构语义,例如.btn、.btn__text - 用 Sass 的
map建立映射表,把块名转成变量前缀,但不耦合值本身:$components: ( "btn": ( "bg": $color-primary, "radius": $radius-sm ) );然后通过函数生成对应规则,而不是手写.btn { background: map-get(map-get($components, "btn"), "bg") } - 禁止在变量名里硬编码 BEM 字符串(如
$btn-bg),这类变量一换组件就废,且无法被其他块复用
组件库中多个 BEM 块嵌套时,如何防止 __element 名冲突?
比如 .list__item 和 .card__item 都用了 __item,一旦两个组件共存且 CSS 加载顺序不对,样式就会互相覆盖——这不是 BEM 的错,是没守住“块名唯一性”底线。
实操建议:
- 所有块名必须全局唯一,推荐加项目/域前缀,例如
myapp-card、myapp-list,而不是泛泛的card - 禁止跨块复用相同元素名(如
__content),哪怕语义一致;myapp-card__body和myapp-list__content就是不同东西,不能省略块名强行统一 - 用 PostCSS 插件
postcss-bem-linter在构建时校验命名合规性,比人工 review 更可靠;它能报出.card .card__title这种非法嵌套,也能发现未声明的__xxx
真正难的不是写对一个组件,而是当十几个 BEM 块、几十个 Sass 文件一起编译时,命名空间是否还干净、选择器是否仍可控。这点很容易被忽略,直到上线后某个按钮突然变色才去翻编译后的 CSS 源码。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











