bem中&易翻车因它仅原样替换父选择器,不保证语义正确;正确用法仅限&__element、&--modifier、&:hover三类,禁用嵌套后代选择器及跨层拼接。

直接用 & 嵌套写 BEM,不加约束会产出语义错位、无法复用的 CSS 类——比如 .button.button--primary:hover 这种冗余结构,或更糟的 .form__field .input(漏了 __,破坏原子性)。
为什么 & 在 BEM 里容易翻车
很多人以为 & 就是“自动拼前缀”,其实它只是原样替换父选择器。一旦嵌套层级或写法松动,就立刻偏离 BEM 原则。
-
.card { &__header { &--large { ... } } }编译出.card__header--large,语义是“header 自身变大”,但若想表达“整个 card 处于 large 状态下的 header”,应写成.card--large .card__header -
.btn { &:hover { &__icon { ... } } }会生成.btn:hover .btn__icon—— 含空格的后代选择器,违背 BEM 扁平性,也拖慢渲染 -
.menu { &__item { a { ... } } }输出.menu__item a,用标签名绑定,HTML 换成nav就失效
安全使用 & 的三条铁律
只允许以下三种写法,其他一律禁用:
-
&__element:必须直属于块,不跨层,如.card { &__title { ... } }→.card__title -
&--modifier:修饰符必须作用于块本身,如.card { &--featured { ... } }→.card--featured -
&:hover、&:focus等伪类:仅用于状态显式控制,且必须配合 JS 切换类名,避免依赖 DOM 层级
禁用:& .child、& > *、& + *、&__item a、&__item p。
如何让 &__text 和 &__text--happy 共享基础样式
上面那个 .emotion__text outline 不生效的问题,本质是类名没共存。BEM 不靠继承,靠显式组合。
- HTML 必须同时带基础类和修饰符:
<div class="emotion__text emotion__text--happy"> <li>Sass 中不要嵌套修饰符在元素下:<code>.emotion { &__text { outline: 1px solid blue; } &__text--happy { color: rebeccapurple; } } - 或者统一用
@at-root提一层,避免误嵌套:.emotion__text { outline: 1px solid blue; @at-root .emotion__text--happy { color: rebeccapurple; } } - 搜索空格:
grep -r " \." src/css/,确认没有.block .element类型选择器 - 检查修饰符是否独立存在:
.button--disabled不能只定义 hover 效果,得包含所有 disabled 状态所需样式(颜色、指针、透明度等) - 验证元素类是否可单独使用:
.card__body单独加到任意 DOM 节点上,样式是否仍按预期生效?如果不是,说明它偷偷依赖了.card的上下文
编译后必须人工检查的三处
光看 Sass 源码没用,最终 CSS 才是运行时依据:
真正难的不是写对 &,而是让每个类名在脱离原始 DOM 结构后依然自洽——这需要从第一行 HTML 就开始约束,而不是靠 Sass 工具兜底。











