最高效安全的BEM写法是直接用&__element和&--modifier;变量拼接或通用mixin会破坏作用域、干扰工具识别、引发样式泄漏,且违背BEM语义优先原则。

直接写 &__element 和 &--modifier 是最高效、最安全的方式;所有试图用变量拼接类名或封装“通用BEM mixin”的做法,反而增加理解成本、破坏作用域约束、且在 CSS Modules 或构建工具链中容易出错。
为什么 &__text 比 .@{block}__text 更可靠
Less 的 & 是唯一能保证父选择器上下文不丢失的机制。写 .button { &__text { ... } } 编译后是 .button__text;而用字符串插值 .@{block}__text 会脱离当前作用域,生成平级选择器,导致:
- 无法继承父级的命名空间(比如
.ui-kit .button__text变成孤立的.button__text) - VS Code、Stylelint 等工具无法识别 BEM 语义,失去自动补全和校验
- 当多个 block 共享相同元素名(如都叫
title),纯插值无法隔离,.card__title和.modal__title会互相干扰 - 编译时无报错,但运行时样式泄漏——这是最隐蔽也最难调试的问题
& 必须显式写出,漏写就变后代选择器
常见错误是省略 &,比如写成:
.button {
__text { font-size: 14px; }
}
这会被编译为 .button __text(空格 → 后代选择器),不是 .button__text。后果包括:
- 样式权重飙升(.button .button__text vs .button__text),后续覆盖困难
- 无法独立使用该类名(
class="button__text"单独加在 HTML 上无效) - 违反 BEM “元素必须依附于块” 的核心原则
正确写法只有一条:所有 BEM 元素和修饰符前必须带 &,且紧贴着写,中间不能有空格或换行干扰。
修饰符复用别靠全局 mixin,用嵌套守卫更轻量
多个 block 都需要 --disabled,不必抽象成 .bem-modifier(disabled) 这种通用 mixin。直接在各自 block 内复用嵌套逻辑更清晰:
.button {
&--disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.input {
&--disabled {
background: #f5f5f5;
}
}
这样做的好处:
- 每个 block 的
--disabled样式可以差异化,不用绕一圈进 mixin 参数判断 - IDE 能准确定位到具体 block 的修饰符定义,跳转和搜索更直接
- 避免 mixin 嵌套过深导致编译慢(尤其在大型项目中,参数化 mixin + guard 多层嵌套会显著拖慢 Less 编译)
- HTML 中写
class="button button--disabled"语义明确,无需额外文档说明 mixin 调用方式
嵌套层级别超三层,否则 BEM 就失效了
BEM 的本质是扁平化职责划分,不是 HTML 结构映射。写成这样就错了:
.card {
.header {
&__title { ... } // → .card .header .card__title
}
}
它编译出的选择器多了一层无关的 .header,既没语义也不必要。真正该写的只有:
.card {
&__header { ... }
&__title { ... }
&--featured { ... }
}
记住:BEM 类名中的 最常被忽略的一点:BEM 不是写给 Less 看的,是写给人和 HTML 看的。类名是否易读、是否能在 DevTools 里一眼定位、是否方便服务端渲染或 SSR 注入 class,这些比“看起来很酷的 mixin 封装”重要得多。__ 和 -- 是命名约定,不是 DOM 层级。HTML 里
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











