<p>SCSS 的 & 符号不能简写 BEM 的 __ 和 -- 类名,因其会原样拼接父选择器并保留空格,生成错误的后代选择器;正确做法是用 @at-root + 插值在根层级生成单类名,确保 BEM 扁平化与可维护性。</p>

SCSS 的 & 符号不能直接简写 BEM 的 __ 和 -- 类名,强行用 &__title 会生成带空格的后代选择器(如 .card .card__title),完全违背 BEM 扁平化原则。
为什么 &__element 会编译出错误选择器
SCSS 中 & 代表的是当前完整父选择器字符串,不是“块名”本身。它会原样拼接,空格也被保留:
-
.card { &__title { color: red; } }→ 编译为.card .card__title(带空格,是后代选择器) -
.sidebar .widget { &__content { } }→ 输出.sidebar .widget__content,但 BEM 要求的是.widget__content -
.button:hover { &__icon { } }→ 得到非法名.button:hover__icon,浏览器直接忽略该规则
正确做法:用 @at-root + 插值提级
必须跳出嵌套上下文,在 CSS 根层级生成单类名。这是目前唯一可预测、可复用的方式:
-
.card { @at-root #{&}__header { color: #333; } }→ 输出.card__header -
.card { @at-root #{&}--featured { opacity: 0.8; } }→ 输出.card--featured - 若块名来自变量:
$block: "button"; @at-root #{$block}__icon { ... } - 所有
__和--必须与块定义同级,不能嵌在&:hover、.header或@media内部
循环生成 BEM 类名时插值要加引号
修饰符或元素名是字符串字面量,不加引号会被 SCSS 当作未定义变量报错:
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:
@each $modifier in ("hover", "disabled") { .btn--#{$modifier} { ... } } - ❌ 错误:
@each $modifier in (hover, disabled) { ... }→ 报Undefined variable "$hover" - 元素批量生成更稳妥用变量拼接:
$block: "card"; @each $el in ("header", "footer") { .#{$block}__#{$el} { ... } } - 避免在循环体内用
&__#{$el}——&仍指向外层块,容易产出意外空格
BEM 的解耦效果不来自 SCSS 语法糖,而来自对类名归属的显式约束。哪怕 @at-root #{&}__title 编译正确,如果 HTML 没写 class="card__title"(漏掉 card 块名或写成 card-title),样式就彻底失效,且极难定位。


















