根本原因是生成的选择器违反浏览器解析规则或语义错位:空格导致后代选择器误匹配、&未紧贴伪类使:hover编译为孤立无效选择器、伪类顺序非法(如:hover:active)、:not()内&位置错误、动态添加的class无法被静态&绑定。

根本原因不是Less编译失败,而是生成的选择器违反浏览器解析规则或语义错位——比如空格、&位置错误、伪类顺序非法、目标元素缺失,都会让:hover变成无效CSS。
空格导致选择器语义完全翻车
Less里写 & :hover(注意中间空格)会编译成 .btn :hover,这是后代选择器,匹配的是「.btn 内部任意子元素的 hover 状态」,而非按钮自身。而 &:hover(紧贴无空格)才编译为 .btn:hover,这才是你想要的。
- ❌ 错误:
& :hover { color: red; }→ 编译后无法触发按钮自身悬停 - ✅ 正确:
&:hover { color: red; }→ 编译后精准绑定目标元素 - ⚠️ 隐患:SCSS/Less嵌套中,一个不小心多敲的空格,就让整条规则失效,且开发者工具里看不出语法报错
& 在多层嵌套或 mixin 中只绑定最近父级
当嵌套在媒体查询、mixin 或 BEM 修饰符里时,& 不会“穿透”中间的类名去绑定最外层元素。例如:
.card.is-active {
@media (min-width: 768px) {
&:hover { opacity: 0.8; }
}
}
编译结果是 .card.is-active:hover,权重升为 0-2-1,且语义变成「同时拥有两个类的元素悬停」,而不是「.card 处于 is-active 状态时悬停」。
立即学习“前端免费学习笔记(深入)”;
- 想表达状态+交互,应改用语义化修饰符:
.card--active:hover - 若必须复用逻辑,把
&:hover拆到顶层,避免嵌套过深导致&绑定失焦 - mixin 内直接写
:hover或& :hover是常见陷阱——&无绑定目标,编译后变成孤立的:hover,浏览器直接丢弃
伪类链顺序违法 LVHA 或被浏览器忽略
Less不校验伪类顺序,但浏览器会拒绝非法组合。例如 &:focus:invalid 看似合理,但旧版 Safari 不支持连用,且若父选择器为空(如在变量块里定义),编译后变成 :focus:invalid(无元素名),直接失效。
- ✅ 安全写法:
input[required]:focus:invalid—— 显式限定元素类型,规避兼容性风险 - ❌ 危险写法:
&:active:hover→ 浏览器按规范忽略,应始终按 LVHA 顺序::link → :visited → :hover → :active - ⚠️ 注意:
:not()内&的位置极敏感:&:not(:disabled):hover合法;&:not(&:disabled)语法错误;&:not(:disabled) :hover变成后代选择器,语义全错
真正难定位的是动态类名与 & 的脱节
Less 编译是静态的,& 只认源码里字面最近的父选择器。如果运行时通过 JS 动态加 class(比如 theme-dark),& 不会自动感知或拼接——你写的 &:hover 还是绑定原始类名,新 class 下的样式自然不生效。
- 这类问题在组件库、主题切换场景高频出现,但开发者工具里看到的选择器是“对的”,实际却没命中
- 不要指望
&能桥接运行时状态,需靠 CSS 自身可扩展性解决:用更宽泛但可控的选择器(如[class*="theme-"]:hover),或交由 JS 控制类名 + 纯 CSS 规则分离 - 伪元素拼接也同理:
&::after正确,& ::after(空格)就变成匹配子元素的伪元素,99% 场景不是你想要的


















