&__element 在子选择器中编译出错,是因为 & 始终代表紧邻上一层的选择器字符串,而非视觉父块名;在嵌套子选择器内使用时,& 指向子选择器自身,导致生成非法类名(如 .button:hover__icon)或语义错乱(如 .card .header__title),违背 bem 扁平命名与单块归属原则。

为什么 &__element 在子选择器里会编译出错的选择器
因为 & 永远只代表**紧邻上一层的选择器字符串**,不是“视觉上的父块名”。写在子选择器内部时,& 就不再是块名,而是那个子选择器本身。
常见错误:
-
.card { .header { &__title { } } }→ 编译为.card .header__title(语义错乱,header__title不属于 BEM 的card块) -
.button { &:hover { &__icon { } } }→ 编译为.button:hover__icon(非法类名,浏览器直接忽略) -
.sidebar .widget { &__header { } }→ 编译为.sidebar .widget__header(丢失.sidebar与.widget的语义绑定,且违背 BEM 单块归属原则)
@at-root #{&}__element 是唯一安全的写法
必须跳出嵌套上下文,在 CSS 根层级拼接类名,才能确保输出的是扁平、无空格、可独立使用的单类名。
正确示例:
-
.card { @at-root #{&}__header { color: #333; } }→ 输出.card__header -
.card { @at-root #{&}--loading { opacity: 0.7; } }→ 输出.card--loading - 变量也适用:
$block: "button"; @at-root #{$block}__icon { ... }
禁止在 @media、&:focus 或任何伪类/属性选择器内部再用 @at-root #{&}__xxx —— 输出顺序不可控,且破坏 BEM 的逻辑层级。
BEM 的 __ 和 -- 必须和块定义同级
BEM 的核心是扁平命名,不是结构派生。所有 __ 元素和 -- 修饰符的 CSS 规则,必须和块选择器处于同一逻辑层级。
✅ 正确:
.button {<br>
@at-root #{&}__icon { … }<br>
@at-root #{&}--disabled { … }<br>
}
❌ 错误:
.button {<br>
&:disabled {<br>
@at-root #{&}__icon { … } // 这会让 .button__icon 依赖状态,违反 BEM 原则<br>
}<br>
}
真实场景中,.button__icon 的禁用态应单独写:.button__icon.button--disabled { … },或用 @extend 复用状态样式。
HTML 类名缺失比 SCSS 写错更隐蔽
SCSS 编译出 .card__title 很容易,但 HTML 里如果只写了 class="card__title" 而漏掉 card,样式就完全不生效 —— DevTools 里查不到规则,控制台也没报错,只能靠肉眼比对。
真正容易被忽略的是:BEM 的解耦效果不来自 SCSS 语法糖,而来自对类名显式归属的强制约束。哪怕 @at-root 用得再准,只要 HTML 没同步写全 card card--featured card__title card__title--large,整个链路就断了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











