Less的when守卫仅在编译期匹配变量值,不能用于伪类(如:hover、:focus)匹配;它只控制mixin是否展开,不生成或感知DOM状态,正确用法是依变量值输出静态CSS规则。

Less的when守卫不能用于伪类匹配
直接在when里写:hover或:focus是无效的——when只在编译期比对变量值,不感知DOM状态或用户交互。你看到的“伪类Guard”其实是误用术语,真实场景中它只能配合变量做静态分支,比如@state: disabled,而非&:hover。
常见错误现象:.btn when (@state = hover) { color: red; } 编译后根本不会生成.btn:hover规则,因为when不处理选择器结构,只控制该mixin是否被展开。
-
when必须写在mixin定义末尾,且只能作用于整个mixin块 - 想输出
:hover,得手动写进选择器里:&:hover { ... },而不是塞进when条件 - 若真要按状态生成不同伪类,应拆成多个mixin:
.btn-hover()、.btn-focus(),再由调用者决定用哪个
用when控制状态类的参数化输出
真正适合when的场景,是根据传入的状态变量(如@mode: dark或@size: large)生成不同数值的CSS声明,比如禁用态在深色模式下用更浅的灰度。
示例:一个带主题适配的.state()混入
立即学习“前端免费学习笔记(深入)”;
.state(@mode: light) when (@mode = light) {
opacity: 0.6;
color: #999;
}
.state(@mode: dark) when (@mode = dark) {
opacity: 0.5;
color: #666;
}
调用时写.is-disabled { .state(dark); },就能输出对应深色模式下的禁用样式。
- 多个
when用逗号分隔表示“或”,同一when内用and连接多个条件,如when (@mode = dark) and (@state = disabled) - 别漏空格:
when (@mode=dark)会编译失败,必须是when (@mode = dark) -
when不支持运行时切换——改@mode值后必须重新编译Less,不能靠JS动态切
为什么不该把:hover和.is-disabled混为一谈
伪类:hover是浏览器根据鼠标位置实时匹配的,而.is-disabled是开发者通过JS或框架明确添加/移除的class。两者生命周期、控制权、可测试性完全不同。
混淆会导致三类问题:
- 禁用按钮仍触发
:hover动画,视觉上像能点,但实际点不动 - SSR渲染时
:hover无法生效,导致首屏样式与客户端不一致 - 媒体查询(如深色模式)无法覆盖
:hover的颜色,但可以精准重写.is-disabled的color
正确做法是:用.is-disabled控制禁用逻辑,用单独的&:hover:not(.is-disabled)控制悬停反馈——两者正交,互不干扰。
状态叠加时when的局限性与替代方案
when无法判断一个元素是否同时拥有.is-error和.is-disabled——它只认变量,不读DOM class列表。所以别指望用when (@state = error and @state = disabled)生成组合样式。
真实项目中,多状态叠加靠的是CSS层叠顺序和显式选择器:
- 优先用单一状态类 + JS保证互斥(禁用时主动移除
.is-error) - 若必须共存,手写
.is-error.is-disabled { color: #666; },清晰可控 - 用BEM修饰符(如
.btn--error.btn--disabled)天然提升权重,避免被覆盖
复杂状态流转(比如加载中+禁用+错误)不是when能兜住的,得靠组件层逻辑收敛,再映射到少数几个class上——预处理器只负责把每个class的样式写干净,不负责状态调度。


















