& 在 sass 中是当前选择器的完整上下文引用,保留所有祖先信息(含伪类、属性选择器等),用于精准生成 bem 平级结构,不可单独使用或后加空格,需配合括号处理伪类、避免多层嵌套滥用。

什么是 & 在 Sass 中的真实作用
它不是“父选择器复制”,而是“当前选择器的完整上下文引用”。BEM 的 block__element--modifier 结构依赖嵌套语义,而 & 正是让这种语义在编译时可预测的关键。很多人误以为它只拼接字符串,其实它会保留嵌套层级中的所有祖先信息(包括伪类、属性选择器等)。
实操建议:
- 只在嵌套规则内使用
&,单独写&会报错:Invalid CSS after "&": expected "{", was ";" - 如果父选择器带伪类(如
.btn:hover),&__icon编译后是.btn:hover__icon—— 这显然错误,必须用括号包裹:(&)__icon才得.btn__icon:hover - 避免多层嵌套中连续用
&,比如& &__item,这会产生重复类名,Sass 不报错但 CSS 无效
怎么用 & 正确写出 BEM 的修饰符和元素
BEM 要求 block__element 和 block--modifier 必须平级,不能出现 .block .block__element 这种后代写法(那会破坏样式隔离)。& 是唯一能自然生成这种平级关系的方式。
常见错误现象:写成 .card { &__header { ... } &--featured { ... } },结果编译出 .card__header 和 .card--featured —— 看似对,但一旦 .card 被套在另一个选择器里(如 .layout > .card),&__header 就变成 .layout > .card__header,破坏了 BEM 的独立性。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 把 block 定义为顶层类名,不嵌套在其他选择器下:
.card { ... },而不是.layout { .card { ... } } - 元素和修饰符统一用
&__xxx/&--xxx,不要混用.card__xxx字面量(否则无法继承父选择器的媒体查询或状态) - 需要响应式变体时,直接在 block 下写
@media (min-width: 768px) { &--large { ... } },&会自动带出.card--large
.card {
padding: 1rem;
&__title {
font-size: 1.25rem;
}
&--compact {
padding: 0.5rem;
}
&:hover &__title {
text-decoration: underline;
}
}
为什么 & 后加空格会编译失败
这是 Sass 解析器的语法限制:& 后紧接字母、下划线或短横线才被识别为 Parent Reference;一旦中间有空格,它就变成普通符号,Sass 会尝试解析为选择器组合(比如 & .icon 是合法的后代选择器),但 & __icon 中的 __icon 没有前导点,直接报错:Invalid CSS: "__icon" is not a valid selector。
实操建议:
-
&__icon✅,& __icon❌,&-icon✅,& -icon❌ - 想拼接字符串(比如动态 modifier 名),必须用插值:
#{$block}__#{$element},这时&不适用 - VS Code 或 WebStorm 默认对
&__没有语法高亮,容易看漏,建议开启 Sass 插件并检查编译输出
Sass 4.0+ 中 & 在模块系统里的行为变化
启用 @use 后,& 的作用域仍以当前文件的嵌套结构为准,但它不再能跨模块引用外部定义的父选择器。比如 @use 'base' 引入的 .btn,你在本文件写 .btn { &__text { ... } } 是可以的;但若 .btn 是从另一个模块通过 @forward 暴露的,且该模块内部没用 & 定义子类,则你无法复用它的嵌套逻辑。
实操建议:
- 把 BEM block 的完整结构(含所有
&__/&--)定义在同一个@use模块内,不要拆到多个文件再拼 - 避免在
@forward时用as *,会导致&查找混乱;显式命名更安全:@forward 'components/card' as card-*; - 如果你用 Dart Sass,注意
&在@content块中会被延迟求值 —— 传入的 mixin 若含&,它绑定的是调用处的选择器,不是定义处的
真正难的不是写对 &__item,而是当设计系统要求 card--featured card--inverted 同时存在时,如何让 &--featured&--inverted 这种组合修饰符既可读又不爆炸。这时候 & 本身无能为力,得靠命名约定和自动化工具兜底。









