& 是紧邻上一层选择器的字符串拼接符,空格决定选择器关系:无空格连写(.modal__close)、紧贴加点(.modal.is-open)、有空格后代(.modal .close);伪类伪元素必须紧贴无空格且符号完整;嵌套过深应扁平化而非依赖 & 跨层。

Less 中 & 不是“自动回退父级”的魔法符号,它只代表**紧邻上一层的选择器字符串**;用错空格、跨层幻想、伪类漏冒号,都会让编译结果完全偏离预期。
为什么 & 编译后选择器“断层”或“多了一层”
根本原因在于你误把 & 当作视觉缩进的逻辑继承,而它实际是字符串拼接操作符。写错一个空格,就等于改写了 CSS 选择器关系。
-
.card { .header { color: red; } }→ 编译为.header { }(孤立类,父级丢失) -
.card { & .header { color: red; } }→ 编译为.card .header { }(&后带空格 = 后代选择器,权重+1,且&实际未参与拼接) -
.btn { &:hover { } }✅ 正确;但写成.btn { & :hover { } }❌ 编译出.btn :hover(空格导致变成后代匹配,语义错误) - 检查方式:打开编译后的
.css文件,搜索对应类名,看生成的选择器是否和你写的结构一致
& 拼接类名时,空格决定输出类型
有无空格,直接决定是复合类名、后代选择器还是同元素多类——这是最常踩坑的地方,没有之一。
-
.modal { &__close { } }→.modal__close { }(无空格,连写,BEM 风格) -
.modal { &.is-open { } }→.modal.is-open { }(紧贴无空格,同元素两个类) -
.modal { & .close { } }→.modal .close { }(有空格,后代,权重升高) - 错误示例:
.list { & li { } }→ 实际仍是.list li { },&完全没起作用,纯属冗余
伪类/伪元素中 & 必须紧贴、写全、不加空格
浏览器对伪类顺序(LVHA)、伪元素语法(::before)有严格要求,& 写错位置或漏符号,会导致样式被忽略或解析失败。
-
a { &:hover { } }✅ →a:hover { } -
a { & :hover { } }❌ →a :hover { }(空格变后代,且可能匹配到 a 内任意 hover 元素) -
.badge { &::after { content: ""; } }✅ →.badge::after { }(双冒号,浏览器才认) -
.form input { &:focus:invalid { } }→ 编译为.form input:focus:invalid { },但 Safari 旧版不支持连用,且权重过高;更稳写法是input[required]:focus:invalid { }
嵌套超过三层时,& 不是解药,而是陷阱
想靠 & 在四层嵌套里“跳两级”生成 .card__title?不可能。它每次只回退一级,越深越容易写错,也越难维护。
-
.page { .layout { .content { .card { .title { } } } } }→ 编译为.page .layout .content .card .title(权重 0-5-0,Lighthouse 直接报警) - 正确做法:删掉内层嵌套,改用
&__title或提取独立类名.card-title - 真需要跨层组合(如
.modal.is-open .dialog .close),别硬套&,改用变量暂存:@modal: ".modal"; @{modal}.is-open & { },或直接扁平化写.modal--open .modal__close - 记住:
&的价值是减少手写重复,不是掩盖结构问题;编译后 CSS 是否简洁、可预测,比源码缩进是否整齐重要得多
最易被忽略的一点:& 只在编译期展开,它不感知 HTML 结构。你写了 .card { &__body { } },但 HTML 里是 class="card"><div class="body"></div>,那这个样式永远不生效——问题不在 Less,而在 class 名脱节。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











