Less 中 & 只支持三类安全 BEM 拼接:&__element、&--modifier、&:pseudo(或&::pseudo),其他用法易出错;它仅字面拼接,不理解 BEM 语义,错误使用会导致类名非法或样式失效。

Less 里的 & 不是 BEM 语法糖,它只做字面拼接,写错一个空格或位置,编译出来的类名就不是 BEM。
哪些 BEM 结构能用 & 安全生成
只有三类写法能稳定产出合法 BEM 类名,其他都容易出错:
-
&__element:如.card { &__header { } }→.card__header -
&--modifier:如.btn { &--primary { } }→.btn--primary -
&:pseudo或&::pseudo:如.btn { &:hover { } }→.btn:hover,注意&和:之间不能有空格
这三类之所以安全,是因为它们严格对应 BEM 的块(Block)、修饰符(Modifier)、状态(Pseudo)三层语义,且 Less 编译器对这三种拼接模式有明确支持。
& 写错位置的典型错误现象
常见报错或隐性失效,往往源于对 & 行为的误解:
立即学习“前端免费学习笔记(深入)”;
- 漏写
&:写成.btn { __icon { } }→ 编译为.btn __icon(后代选择器,不是.btn__icon) -
&和连接符贴太紧:.btn{&--large__icon{}}→.btn--large__icon,BEM 规范禁止修饰符直接带元素,应拆成.btn--large .btn__icon - 在媒体查询里直接用:
@media (max-width: 768px) { & { } }→ 报ParseError;必须先有外层选择器,再进@media块内用& - 多父选择器共用:
.btn, .link { &__icon { } }→ 只绑定到.link,.btn被忽略;&永远只认最近一个父级
为什么别用变量拼接代替 &__xxx
有人想用 @block: "card"; .@{block}__header { } 绕过嵌套,但这会破坏 BEM 的上下文约束:
- 生成的是平级类,丢失与
.card的样式继承关系(比如.card上设的font-family不会自然透传) - VS Code、Stylelint 等工具无法识别该类为合法 BEM 元素,失去语法提示和校验
- 若父选择器本身含层级,如
.container .card,extract(&, 1)可能取到.container而非.card,直接崩 - Less 4.0+ 已废弃
~".@{name}"用于选择器,新版直接报Invalid CSS after ""
BEM 场景中 & 明确不该用的地方
一旦脱离“单块 + 固定连接符”这个最简模式,& 就不再可靠:
- 动态主题类:
.header.theme-dark下想定义.header__title,.header { &__title { } }只能生成.header__title,不继承.theme-dark——&不认运行时类名 - 跨组件复用元素:
.modal__close和.drawer__close需相同样式,用&__close得重复写两遍;不如定义原子类.close-btn - 需要后代关系时:
.card__body .card__title是合法 BEM,但.card__body { & .card__title { } }会生成相同选择器,可读性差且 DOM 变化后易失效 - 伪元素 + 修饰符组合:
.btn--large { &__icon::after { } }→.btn--large__icon::after,但你真正想要的可能是.btn__icon--large::after,这时&无法自动切换修饰符归属层级
真正难处理的不是语法怎么写,而是当 & 被嵌在多层 @media、@supports 或条件 mixin 里时,它只绑定字面最近的父选择器——这个限制不会报错,直到某天样式突然不生效才暴露出来。


















