推荐使用支持任意数量阴影、自动过滤空值的 .box-shadow(@shadows...) Mixin,通过 length()、extract() 和递归 .loop() 拆分并拼接各阴影值,确保生成合法无引号、无换行的 CSS box-shadow。

如何用 Less 封装支持多组值的 box-shadow Mixin
Less 本身不支持直接传入不定长参数列表(如 ...args),但可以通过「逗号分隔的值」+ extract() + 循环拼接的方式,实现真正可用的多阴影封装。关键不是“能不能写成一个 mixin”,而是“能否自然地传入 1 个或 5 个阴影,且语义清晰、无冗余空格或语法错误”。
为什么不能直接用 @arguments 拼接?
直接写 .shadow(@shadows...) { box-shadow: @arguments; } 看似简洁,但实际会出问题:Less 把 @arguments 当作单个值处理,若传入 .shadow(0 2px 4px rgba(0,0,0,.1), 0 8px 16px rgba(0,0,0,.08)),最终生成的 CSS 里会出现多余引号或换行,导致浏览器解析失败。
必须把传入的阴影列表拆成独立项,再用 join() 或循环拼接为合法 CSS 值。
-
join()更简洁,但只适用于所有阴影都已作为单个参数传入(即用逗号明确分隔) - 若需支持嵌套变量(如
@shadow-sm、@shadow-lg)或动态组合,就得用each()配合length()和extract() - 注意:Less v3.10+ 才支持
each();旧版本需降级为递归 mixin
推荐的生产级 Mixin 写法(兼容 v3.10+)
以下 mixin 支持任意数量阴影,自动过滤空值,保留原始空格格式:
立即学习“前端免费学习笔记(深入)”;
.box-shadow(@shadows...) {
@shadow-list: @shadows;
@n: length(@shadow-list);
@result: "";
.loop(@i) when (@i =< @n) {
@item: extract(@shadow-list, @i);
@result: e("@{result}@{item}");
.loop((@i + 1));
}
.loop(1);
box-shadow: ~"@{result}";
}
使用示例:
.card {
.box-shadow(
0 1px 3px rgba(0,0,0,.1),
0 2px 6px rgba(0,0,0,.08)
);
}
生成结果正确无引号:box-shadow: 0 1px 3px rgba(0,0,0,.1), 0 2px 6px rgba(0,0,0,.08);
- 必须用
e()或字符串插值~"..."绕过 Less 的转义保护 - 避免在
@shadows...中混用分号或换行——Less 解析时会截断 - 如果某组阴影是变量(如
@shadow-base),确保它本身是字符串形式,而非带单位的数值计算式
更轻量的方案:用 join() + 显式数组
如果你的项目中阴影组合固定、可预定义,用 join() 更安全直观:
.box-shadow-joined(@shadows: ()) {
@cleaned: replace(join(", ", @shadows), " , ", ",");
box-shadow: ~"@{cleaned}";
}
// 使用
.shadow-card {
.box-shadow-joined(
"0 1px 3px rgba(0,0,0,.1)",
"0 2px 6px rgba(0,0,0,.08)"
);
}
这个写法绕开了循环,性能更好,也更容易调试。缺点是每个阴影必须加引号,否则 Less 会尝试计算(比如把 0 2px 6px 当作三个独立变量)。
- 引号是必须的——这是 Less 区分“字符串”和“表达式”的唯一方式
-
replace()是为了清理join()可能引入的多余空格(如前后有空格时) - 不推荐在 mixin 内部做颜色/尺寸计算,应由调用方完成,保持职责清晰
真正难的不是写出能跑的 mixin,而是让团队其他成员能一眼看懂传参规则、不因少写一个引号或错用空格而白花半小时查渲染异常。所以优先选显式、可读性强的方案,哪怕多敲几个双引号。


















