Less 中的 & 不是智能拼类名语法糖,而是原样插入父选择器字符串;遇空格即生成后代选择器,仅绑定最近父级,不穿透多层,不解析 BEM 语义,也不响应动态类名。

Less 中的 & 不是“智能拼类名”的语法糖,它只是把当前父选择器字符串原样插入——空格、冒号、连字符的位置稍有偏差,生成的 CSS 就完全跑偏。
为什么 & :hover 编译成后代选择器而不是自身伪类
Less 规则极其简单:& 后面**只要出现空格**,就认定为分隔符,强制生成空格分隔的选择器(即后代关系)。这不是 bug,是设计行为。
-
&:hover→ 编译为.btn:hover(正确) -
& :hover→ 编译为.btn :hover(错误:匹配 .btn 内部任意可悬停的子元素) - 同理:
& ::before→.icon ::before,而非.icon::before,后者在多数浏览器中不生效
嵌套多层时 & 只绑定最近父级,不是整条路径
& 永远只展开为**直接上一行写的选择器**,不会向上穿透。很多人误以为 .card { .header { &__title { } } } 会生成 .card__header__title,其实编译结果是 .card .header__title。
- 原因:.header 是独立选择器,
&绑定的是它,不是 .card - 想得到
.card__header__title,得写.card { &__header { &__title { } } }(显式两层&) - 超过 3 层嵌套 +
&容易产出语义错乱、权重失控的选择器,建议拆成平级 BEM 类
用 & 拼 BEM 修饰符时,&--large 和 &__text--large 语义完全不同
BEM 的 -- 修饰符应作用于块(Block),不是元素(Element)。但 & 不解析语义,只做字面拼接——你写什么,它就输出什么。
立即学习“前端免费学习笔记(深入)”;
-
&--large→.btn--large(合法,修饰块) -
&__text--large→.btn__text--large(语法合法,但违背 BEM 原则:--large 应修饰.btn,而非.btn__text) - 正确做法:需要
.btn--large .btn__text这种组合时,应写.btn--large { &__text { } },让修饰符控制上下文
媒体查询里 & 无法响应 JS 动态添加的类名
& 在 @media 或 mixin 中,依然只认静态声明时的最近父选择器。它不感知 DOM 变化,也不支持运行时条件。
-
.card { &.theme-dark { color: white; } }→ 编译为.card.theme-dark { },纯静态规则 - 如果
.theme-dark是 JS 后加的,这条规则不会“激活”,也不会重新计算 - 动态主题建议用 CSS 自定义属性(
--card-color)+:root控制,而非依赖&拼类
最稳妥的调试方式,永远是看编译输出:lessc input.less --no-color | grep "btn",确认生成的选择器是否和你手写的完全一致——别猜,别试,直接验证。


















