Less不支持原生for循环,v4.0+用each()配合字面量数组生成CSS色阶变量,v3.x需用带守卫的递归混合实现;色阶计算须在each或递归体内进行,避免提前求值失败。

用 for 循环生成色阶变量时,Less 不支持原生 for
Less 没有 for 语句,强行写 for (let i = 1; i 会直接报错:ParseError: Unrecognised input。必须改用 Less 的递归混合(.loop())或已内置的 each()(v4.0+)。旧版本只能靠递归——它本质是函数式展开,不是运行时循环。
实操建议:
- 确认 Less 版本:
lessc --version;v4.0+ 优先用each(),更直观 - 递归混合必须带终止条件,否则编译卡死(比如忘记
when (@i > 10)) - 不要在递归里拼接选择器(如
.color-@{i}),只生成变量;CSS 变量需挂载到:root或作用域内
each() 配合数组生成 --color-primary-1 到 --color-primary-10
v4.0+ 的 each() 是最接近“批量”的写法,但它的参数是「键值对数组」,不是纯数字序列,所以得先构造数组。注意:数组元素必须是明确的值,不能是计算表达式(如 lighten(@base, 10% * @i) 不能直接塞进数组)。
示例(生成 10 级主色):
@primary-steps: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
@primary-base: #3b82f6;
<p>each(@primary-steps, {
@step: @value;
@lightened: lighten(@primary-base, (10 - @step) * 4%);
:root {
--color-primary-@{step}: @{lightened};
}
});
</p>
关键点:
-
@primary-steps必须是逗号分隔的字面量列表,不能是1 + 1, 2 + 1 -
@value是当前项值(即 1、2…),@key是索引(从 0 开始),这里用不到 - 色阶计算放在
each块内,避免提前求值失败
用递归混合兼容老版本 Less(v3.x)
v3.x 只能靠带守卫的递归混合模拟循环。它编译时展开所有层级,所以性能无问题,但写错守卫条件会导致无限展开、内存溢出。
标准写法:
.generate-color-scale(@base, @i: 1, @total: 10) when (@i =<p>容易踩的坑:</p>
- 守卫条件写成
when (@i 会漏掉最后一级(@i=10 不满足) - 忘记递归调用语句,就只生成第一级
- 把
:root写在混合外部,变量不会被注入到根作用域
主题切换时,别直接覆盖 :root 变量,用 CSS 类控制作用域
如果项目要支持亮/暗主题,别用多个 :root { --color-primary-1: ... } 覆盖——后写的会生效,但无法同时存在两套色阶。应该把变量挂到带 class 的选择器下,比如 .theme-dark :root,再用 JS 切换 class。
推荐结构:
.theme-light :root {
--color-primary-1: #dbeafe;
--color-primary-2: #bfdbfe;
/* ... */
}
.theme-dark :root {
--color-primary-1: #1d4ed8;
--color-primary-2: #1e40af;
/* ... */
}
这样做的实际好处:
- 无需 JS 动态重写 CSS 变量,纯 class 切换即可
- 避免变量名冲突(比如
--color-primary-5在不同主题下含义不同) - 开发者工具里能清晰看到哪套变量当前生效
真正麻烦的是色阶逻辑本身——lighten() 在深色背景下可能生成不可见的浅灰,得配合 contrast() 或手动定义明度映射表。这点没法靠批量生成自动解决。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











