& 不是给CSS加权重,而是将父选择器原样拼接到子规则中生成新选择器,从而间接影响特异性;它必须位于嵌套规则首位,适用于需复用语义化上下文的场景,BEM更适配样式变体。

Less里用&提升选择器特异性,不是加权而是拼接
直接说结论:& 不是给CSS“加权重”,而是把父选择器原样插入到子规则中拼成新选择器。它改变的是生成后的CSS结构,从而间接影响特异性。很多人以为写 &.active 是“强化当前选择器”,其实只是让编译结果多了一层嵌套前缀。
常见错误现象:在组件内部写 .btn { &.primary { color: blue; } },本意是想让 .btn.primary 比 .primary 优先级高,结果发现样式没生效——问题往往出在父选择器本身层级太浅,或外部有更长的选择器覆盖了它。
-
&必须出现在嵌套规则第一位置,不能写成.primary { &.btn { ... } } - 如果父选择器是
#header nav,那么&.mobile编译后是#header nav.mobile,特异性为 1-1-1(ID + 类 + 元素),比单纯.mobile(0-1-0)高得多 - 过度嵌套
&容易产出冗余选择器,比如.card { &__title { &.large { ... } } }会生成.card__title.large,但实际可能只需要.card__title--large
什么时候该用&,什么时候该换BEM命名
用 & 的核心场景是:需要复用父上下文,且该上下文本身具有语义约束(比如组件容器、状态容器)。不是所有嵌套都需要 &,尤其当目标是控制样式变体时,BEM后缀更轻量、更可预测。
使用场景对比:
立即学习“前端免费学习笔记(深入)”;
- 适合
&:模态框内所有按钮都要禁用状态,且只在.modal.is-open下生效 →.modal { &.is-open { .btn { opacity: 0.5; } } } - 更适合BEM:按钮尺寸变体 → 直接写
.btn--large,而不是.btn { &--large { ... } },避免生成无意义的.btn.btn--large(特异性没增,还多一个类) - 参数差异明显:
&依赖父选择器真实存在并被正确应用;BEM类名是扁平、自包含的,不依赖DOM结构深度
编译后特异性计算容易踩的坑
Less不参与浏览器渲染,它只负责输出CSS。所以“提高优先级”最终看的是生成的CSS选择器是否真的更具体。很多问题其实是编译前后不一致导致的。
常见错误现象:开发时样式生效,上线后失效——很可能是构建工具(如Webpack + less-loader)默认开启了 math: always 或压缩选项,意外改变了嵌套逻辑;或者用了 @plugin 引入的扩展改变了 & 行为。
- 检查编译输出:把
.a { &.b { color: red; } }放进在线Less编译器,确认输出是.a.b { color: red; }而不是.a .b(中间有空格就完全不是一回事) - 避免和CSS-in-JS混用:如果同时用Styled Components或Emotion,它们的动态类名会打乱你对特异性的预判,
&生成的静态选择器很可能被运行时注入的更高权重要素覆盖 - IE兼容性注意:某些老版本less.js(& 处理异常,比如
&:hover &::before可能漏掉第一个&
真正决定特异性的,是最终CSS字符串长度和类型组合
别迷信 & 能“自动提权”。一个 div#main ul li a:hover 即使不用Less也能压过 .nav-link.active。Less只是帮你少写几遍重复前缀,但它不会绕过CSS特异性计算规则。
最容易被忽略的一点:伪类和属性选择器权重相同,但顺序无关。所以 .btn[disabled] 和 .btn:disabled 特异性一样(0-1-1),但前者在部分旧版iOS Safari中不支持,后者支持更好——这时候选哪个,不是优先级问题,而是兼容性取舍。
复杂点在于:你写的每个 & 都在悄悄延长选择器链。上线前务必用浏览器开发者工具的“Computed”面板,看最终生效的是哪条规则,它的选择器到底长什么样。别靠猜。


















