less的when是编译期guard机制,仅用于mixin定义中实现条件重载,支持=、!=、>、

Less中when关键字的基本写法和作用范围
when不是CSS原生语法,是Less独有的Guard机制,只能用在mixins定义里,不能直接写在普通选择器或属性中。它不改变CSS输出结构,只决定某个mixin是否被调用——条件为真才展开,否则跳过整段逻辑。
常见错误是把它当JavaScript的if用,比如写成.btn when (@size = 'large') { ... },这会报错:Guard只能出现在mixin声明处,不能挂在选择器后面。
- 正确位置:
.btn(@size) when (@size = large) { padding: 12px; } - 支持的比较操作符只有
=、!=、、<code>>=、、<code>>,不支持===或&&/||(需用逗号拼多个条件) - 字符串比较时,
large是无引号标识符,等价于"large";但@size = "large"也合法,推荐统一用无引号写法避免歧义
多个when分支实现类似switch的效果
Less不提供else if,但允许对同一个mixin名定义多个带不同when条件的版本,按顺序匹配第一个为真的分支,其余忽略。这适合做主题色、尺寸分级等场景。
.button-style(@type) when (@type = primary) {
background-color: #007bff;
}
.button-style(@type) when (@type = danger) {
background-color: #dc3545;
}
.button-style(@type) when (@type = default) {
background-color: #6c757d;
}
.button-style(@type) when not (@type = primary), not (@type = danger), not (@type = default) {
background-color: #f8f9fa;
}
注意最后的not兜底写法:它用逗号表示“且”关系,等价于not ((@type = primary) or (@type = danger) or (@type = default))。漏掉not或括号容易误匹配。
- 分支顺序重要:前面的条件更具体,应优先写;否则
default可能提前截断后续分支 - 所有分支必须参数数量和类型一致,否则Less编译器会报
Mixin is not defined - 无法在同一个
when里混用单位比较,比如@size > 12px和@size > 1.2rem不能共存,会触发单位不兼容错误
Guard配合isnumber()、isstring()做类型安全判断
用户传参类型不确定时(比如@padding可能是12、12px或auto),仅靠=比较会失效。isnumber()这类类型检测函数必须和when联用,单独写在mixin体内部无效。
例如想让.pad(@val)自动补单位:
.pad(@val) when (isnumber(@val)) {
padding: @val * 1px;
}
.pad(@val) when (isstring(@val)) and not (iskeyword(@val)) {
padding: @val;
}
.pad(@val) when (iskeyword(@val)) {
padding: @val;
}
-
iskeyword()用于识别auto、inherit这类CSS关键字,它们属于identifier而非string -
isstring()对带引号的"12px"返回true,但对无引号的12px返回false——后者被解析为数值+单位,需用isdimension() - 不要在
when里调用unit()或round()等计算函数,Guard只接受纯判断逻辑,复杂运算得放到mixin体内
嵌套mixin与Guard的陷阱:变量作用域和递归限制
Guard本身不创建新作用域,但嵌套调用时容易因变量覆盖导致条件误判。比如外层mixin设了@theme: dark,内层又定义同名变量,Guard读到的是内层值。
更隐蔽的问题是递归调用:Less默认禁止无限递归,但Guard条件若依赖未初始化变量(如@i: @i + 1),可能绕过检测直接崩溃。
- 调试技巧:用
.debug() when (true) { .debug-info { content: "@theme is @{theme}"; } }临时注入调试样式 - 避免在Guard中引用父级作用域的动态计算结果,比如
@width - @padding * 2 > 100,应先算好再传参 - Less 4.0+支持
when (default())作为兜底分支,但旧版本需用when not (@cond1), not (@cond2)模拟,兼容性要留意
Guard真正难的不是语法,而是把运行时逻辑压缩进编译期静态判断——所有条件值必须在编译前确定,没法读取DOM尺寸或用户交互状态。这点常被初学者忽略,直到在JS动态切换class时发现样式没更新才反应过来。










