& 是 Sass 中唯一能安全复用父选择器的机制;无 & 时 __element 仅生成后代选择器,&__element 才生成扁平类名;&--modifier 必须直接依附块或元素,不可嵌套在子选择器下;BEM 类名需用插值拼接,避免空格和上下文误用。

&<strong>element</strong> 和 &--modifier 不是“中缀连字符语法”,而是必须显式用 & 绑定父选择器的拼接动作;Sass 本身不识别 或 -- 为特殊符号,所有连字符都只是普通字符串,不自动拼接。
为什么直接写 __element 会生成后代选择器?
很多人误以为写成:.block { __element { color: red; } }
就能产出 .block__element。实际编译结果是 .block __element(带空格),即后代选择器——浏览器按“.block 内的任意 __element 元素”匹配,而 HTML 中根本不存在叫 __element 的标签。
根本原因:__element 在 Sass 里只是个无意义的子选择器名,没有 & 就不会复用父类名。
-
&是唯一能安全复用当前块名的机制 - 没
&,就只是普通嵌套,层级照常展开 - 想扁平,就必须让
&直接参与拼接
&__element 必须紧贴使用,中间不能有空格
& __element(带空格)和 &__element(无空格)编译结果完全不同:
前者是 .block __element(后代),后者才是 .block__element(扁平类名)。
常见翻车点:
- VS Code 自动补全插入空格,手快没删干净
- 复制粘贴时带不可见 Unicode 空格(如 )
- 在
&:hover后误写&__icon,结果变成.block:hover__icon(非法类名)
只要 & 后出现空格,Sass 就放弃拼接,退化为默认嵌套行为。
立即学习“前端免费学习笔记(深入)”;
修饰符 &--modifier 不能挂在元素下
BEM 规范要求修饰符必须作用于块或元素本身,不能“派生”新结构。
错误写法:.block { &__item { &--active { } } } → 编译出 .block__item--active,违反 BEM(元素不应带修饰符)。
正确组合方式只有两种:
- 块级修饰符:
&--large→.block--large - 元素级修饰符:
&__item--disabled→.block__item--disabled(注意:是&__item--disabled,不是&__item { &--disabled { } }) - 跨类组合(非嵌套):
@at-root #{&}--large #{&}__item { }→.block--large .block__item
修饰符永远依附于已有块/元素,不创造新命名层级。
循环生成 BEM 类名时,__ 和 -- 必须用插值拼接
SCSS 不允许字符串字面量直接相加:"btn"__"icon" 会报错。连字符必须作为字符串参与插值:
@each $part in ("header", "footer") {<br>
@at-root #{&}__#{$part} { /* styles */ }<br>
}
关键点:
-
$part必须是带引号的字符串("header"),否则被当变量报Undefined variable -
#{&}__#{$part}中的__是纯文本,不是运算符 - 若块名来自变量(如
$block: "card"),应写成.#{$block}__#{$part},避免依赖&的上下文稳定性
嵌套循环里 & 指向的是外层块,不是当前迭代项——这点极易被忽略,导致类名错位。
真正需要警惕的,不是怎么“快速生成”,而是每次敲下 &__ 前,得确认当前作用域是否真的是你要的块级顶层;一旦嵌套过深或伪类介入,& 就不再是那个干净的块名了。


















