Less本身没有.each()函数,所谓“循环”实为递归mixin配合守卫条件实现:定义起始值(如@n: 12),当@n > 0时生成.col-@{n}等类并递归调用自身,守卫为false时终止。

Less 中用 .each() 无法批量生成栅格类?别试了,它不存在
Less 本身没有 .each() 或类似 JavaScript 的数组遍历函数。你看到的所谓“Less 循环”,本质是递归 mixin + guard 条件 + 参数递减,靠编译时展开实现“伪循环”。想直接写 for (let i = 1; i 那种语法?编译器直接报错。
真正能用的是 .loop() 风格递归 mixin,或者更稳妥的 when + + 运算组合。关键不是“怎么写得像 JS”,而是“怎么让 Less 编译器在静态阶段把所有类名展开出来”。
用递归 mixin 实现 1–12 列栅格类(含 offset、push、pull)
核心思路:定义一个带计数器的 mixin,每次生成一组 .col-1 ~ .col-12、.offset-1 ~ .offset-12 等,然后调用自身减 1,直到计数器为 0 时终止(用 when guard 控制)。
.make-grid-columns(@n) when (@n > 0) {
.col-@{n} { width: percentage(@n / 12); }
.offset-@{n} { margin-left: percentage(@n / 12); }
.push-@{n} { left: percentage(@n / 12); }
.pull-@{n} { right: percentage(@n / 12); }
.make-grid-columns(@n - 1);
}
.make-grid-columns(12);
注意三点:
立即学习“前端免费学习笔记(深入)”;
- 必须显式写
.make-grid-columns(12)启动,不能只定义不调用 -
@n / 12是列数比总列数,不是固定像素;如需响应式,需套在媒体查询 mixin 内再调用 - Less 不支持浮点运算截断,
percentage(5 / 12)会输出41.6666666667%,CSS 可接受,但若需精确到小数点后 2 位,得靠构建工具后处理或手动四舍五入(Less 无round()原生函数)
为什么不用 for 或 while?Less 编译期不支持动态控制流
Less 是静态预处理器,所有逻辑必须在编译前完全确定。所谓“循环”,只是开发者用递归 trick 让编译器展开成固定结构。如果写成:
.bad-loop(@i, @max) when (@i =< @max) {
.col-@{i} { width: 100% / @max * @i; }
.bad-loop(@i + 1, @max);
}
表面看没问题,但实际会因 guard 条件未覆盖边界(比如 @i = 缺少 <code>= 严格匹配)导致无限递归,Less 编译器报错 Recursive call of mixin 并中断。
更安全写法是用 > 或 单向判断,配合初始值严格递减/递增,例如 <code>when (@n > 0) 比 when (@n >= 1) 更可靠。
生成响应式栅格时,媒体查询必须包裹整个递归调用
不能把 @media 写在 mixin 内部——那样每个类都会重复嵌套一遍媒体查询,体积爆炸。正确做法是先定义好基础 mixin,再在外层用媒体查询包裹调用:
@media (min-width: 768px) {
.make-grid-columns(12);
}
@media (min-width: 992px) {
.make-grid-columns(12);
}
但注意:这样会为每个断点重复生成全部 12 个类。如果只想在大屏启用 12 列、小屏降为 6 列,就得拆成两个独立 mixin,比如 .make-grid-columns-sm(6) 和 .make-grid-columns-lg(12),否则 CSS 体积会随断点数 × 列数线性增长。
另外,Less 对 @media 嵌套支持有限,避免在 mixin 内写 &:hover 类复合选择器再套媒体查询,容易触发解析异常。


















