Less模式匹配是选择器级函数重载,通过同名混合的多重定义与参数值/类型匹配实现编译期静态分发,仅展开首个完全匹配版本,不匹配定义被忽略。

Less模式匹配不是if-else,而是选择器级别的函数重载
Less没有if语句,所谓“条件逻辑”靠的是混合(.mixin)的多重定义 + 参数值/类型匹配实现。它本质是编译期静态分发:编译器按传入参数逐个比对所有同名.mixin定义,只展开**第一个完全匹配**的版本。不匹配的定义被忽略,不会报错也不会 fallback。
常见错误现象:
- 写了
.btn(@type: primary)和.btn(primary) { ... },但调用.btn(@type)时没生效——因为@type是变量,不是字面量primary,无法触发字面量匹配 - 多个匹配同时成立(比如
.mixin(@a) when (@a > 0)和.mixin(@a) when (@a ),结果只取第一个定义,后一个永远不执行
字面量匹配必须写死参数值,不能用变量代入
想让.icon(@kind)根据@kind输出不同 SVG 背景,就得显式写出每种可能的取值:
.icon(social) {
background-image: url("social.svg");
}
.icon(alert) {
background-image: url("alert.svg");
}
.icon(@_) {
background-image: url("default.svg");
}
这里@_是通配符,匹配任意未被前两条捕获的值;但它只是占位符,不能在内部使用——@_.size这种写法无效。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 匹配只看参数**字面值**,
@kind: social; .icon(@kind);不会命中.icon(social),必须写成.icon(social) - 字面量匹配优先级高于守卫(
when)匹配,所以.icon(social)和.icon(@a) when (@a = social)共存时,前者一定先被选中 - 不要试图用
@_做分支逻辑,它只是兜底,不带任何运行时信息
守卫(when)匹配适合数值/颜色/函数判断,但需注意求值时机
当需要基于计算结果分支时,用when更自然。比如深色背景上文字自动变白:
.text-color(@bg) when (lightness(@bg) >= 50%) {
color: #111;
}
.text-color(@bg) when (lightness(@bg) < 50%) {
color: #fff;
}
注意:
-
lightness()等函数在编译期求值,所以@bg必须是编译期可确定的值(如变量、字面量),不能是运行时才有的 CSS 变量(var(--bg)) - 守卫表达式里不能访问外部作用域变量,除非提前传入:
.text-color(@bg, @fallback: #333),否则@fallback在守卫里不可见 - 多个
when守卫必须互斥,否则只有第一个生效;推荐用=、、<code>>=这类明确边界,避免!=导致逻辑遗漏
混用字面量与守卫时,顺序决定行为
实际项目中常把两者结合:用字面量处理预设类型,用守卫处理动态计算。但顺序很关键:
// ✅ 正确:字面量优先,守卫兜底
.btn(primary) { background: @primary-color; }
.btn(@color) when (iscolor(@color)) { background: @color; }
.btn(@_) { background: @gray-light; }
// ❌ 错误:守卫放前面,字面量永远不触发
.btn(@color) when (iscolor(@color)) { background: @color; }
.btn(primary) { background: @primary-color; } // 这行永远不会进
容易被忽略的细节:
- Less 不支持
else if,也没有default关键字,@_只是语法糖,不是语言特性 - 守卫里的
isnumber()、isstring()等函数返回布尔值,但它们本身不能嵌套在另一个函数里判断,比如if(iscolor(@c), #000, #fff)会报错——Less 没有if()函数 - 调试时加
.debug { content: "@{bg} → @{lightness}这种插值日志没用,守卫内无法输出中间值,只能靠编译报错或拆成独立 mixin 测试


















