less嵌套本质是选择器拼接而非作用域封装,三层以上易导致权重过高、性能下降;&用于拼接而非降权,@at-root用于切断嵌套上下文而非补救深层嵌套。

Less 中的嵌套不是作用域封装,而是选择器字符串拼接——你写的每一层缩进,都会变成编译后 CSS 中一个空格分隔的类名或标签名,直接叠加权重。一旦超过三层,.card .header .title h1 这种 0-3-1 权重就很难被单类名覆盖,!important 就成了补丁常态。
为什么 & 用错会让权重翻倍而不是降权
& 是父选择器的完整副本,不是“当前上下文开关”。它不压缩、不降权,只决定拼接方式。用错等于主动加一层无意义的后代关系。
- 危险写法:
.modal { & .close { opacity: 0.5; } }→ 编译为.modal .close(权重 +1),&完全没起作用 - 危险写法:
.list { & li { margin: 4px; } }→ 实际仍是.list li,和不加&一模一样 - 安全写法:
.btn { &__icon { display: inline-block; } }→ 编译为.btn__icon(单类名,权重恒为 0-1-0) - 安全写法:
a { &:hover { color: blue; } }→ 编译为a:hover(伪类不增加层级计数,权重 0-1-1)
三层嵌套是真实性能与维护临界点
浏览器匹配 CSS 时从右往左回溯,.a .b .c .d 要检查每个 .d 的父、祖父、曾祖父……DOM 节点越多,耗时越呈指数增长。实测在低端 WebView 中,4 层选择器的 Recalculate Style 时间比 2 层高 3–5 倍。
- 三层内(如
.btn { &--primary { &:hover { } } })→ 编译为.btn--primary:hover(0-2-1),安全 - 四层起(如
.card { .body { .title { .highlight { } } } })→ 必然产出 0-3-1+ 权重,且无法靠&降权 - VS Code 的 Less IntelliSense 插件会在第 4 层缩进处标黄——这不是提示“可以再忍”,是在说“现在重构成本最低”
用 @at-root 切断嵌套链,而不是给深层结构打补丁
@at-root 不是“跳出缩进”的快捷键,它是切断当前嵌套上下文对后续规则的选择器前缀继承。它解决的是“不该被嵌套却被动嵌套”的问题,不是给已写完的四层嵌套续命。
- 正确:
.btn { @at-root @media (min-width: 768px) { &--large { font-size: 18px; } } }→ 输出@media (min-width: 768px) { .btn--large { } } - 正确:
.modal { .overlay { @at-root .tooltip { top: -10px; } } }→ 输出.tooltip { top: -10px; },完全脱离父级 - 错误:
.card { .body { .title { @at-root { .highlight { } } } } }→ 语法合法但语义混乱,掩盖了本该删掉的两层缩进
真正卡住人的,不是不会写 & 或 @at-root,而是嵌套写多了,忘了自己正在生成选择器——.a .b .c .d 看着像局部作用域,实际是全局高压线,而且浏览器每次渲染都在默默回溯它。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











