&.active 编译为 .btn.active(同元素双类),&--active 编译为 .btn--active(bem 修饰类),& .active(带空格)编译为后代选择器 .btn .active;& 仅作字符串拼接,不智能识别语义。

直接用 & 就能生成状态修饰符,但多数人写错位置或误解拼接逻辑,结果产出的是后代选择器而非同级类名。
为什么 &.active 和 &--active 编译结果完全不同
& 不是“自动补全”,而是原样复用父选择器字符串。它后面跟什么,就拼成什么。
-
&.active→ 编译为.btn.active(两个类必须同时存在在同一个元素上) -
&--active→ 编译为.btn--active(BEM 风格的独立修饰类) -
& .active(注意空格)→ 编译为.btn .active(后代选择器,完全不是状态修饰)
常见翻车点:手抖多打一个空格,或误以为 & 会“智能识别”BEM 规则,结果样式不生效。
写 &:hover 时要注意 specificity 和伪类顺序
浏览器对伪类的匹配有严格顺序,&:hover 没问题,但混搭时容易踩坑:
-
&:hover:disabled无效 ——:disabled是表单属性伪类,不能和:hover同时作用于可交互元素(按钮禁用后无法 hover) -
&:focus-visible应优先于&:focus,否则会被覆盖 - 若父选择器本身带 class(如
.btn.primary),&:hover会编译为.btn.primary:hover,specificity 升高,可能压过其他规则
批量生成 BEM 修饰符时,& 不能嵌套在循环里直接用
& 总是指向循环外最近的父选择器,不是当前迭代项。想生成 .btn--large、.btn--small,别这么写:
.btn {
@each $mod in ("large", "small") {
&--#{$mod} { font-size: 14px; }
}
}
这段代码实际输出的是:
.btn--large { font-size: 14px; }
.btn--small { font-size: 14px; }
看似对?但问题在于:这两个类被包裹在 .btn { } 块里,SCSS 会尝试把它们当作嵌套规则处理,某些旧版编译器会报错或行为异常。更稳妥的做法是提级:
@each $mod in ("large", "small") {
@at-root .btn--#{$mod} {
font-size: 14px;
}
}
或者干脆不用 &,直接拼字符串:.btn--#{$mod},语义更清晰,也避开了 & 的作用域陷阱。
真正难的不是写对 &,而是意识到它只做静态字符串替换,不感知 DOM、不推理语义、不帮你纠错 —— 所有拼错的空格、连字符、顺序,都会原样进 CSS 文件里,等你调试时才发现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











