Less 4.0+ 支持用 @themes Map + each() 批量生成多主题 CSS 变量,需顶层声明、启用 javascriptEnabled,并通过 .theme-rules mixin 遍历输出 :root[data-theme="x"] 下的 --theme-* 变量,禁止运行时嵌套取值。
Less 4.0+ 原生支持 Map 结构,@themes 是批量生成主题最干净的方式——它不依赖文件复制、不靠 import 顺序覆盖,而是把所有主题色定义在一个对象里,再用 each() 遍历输出 :root[data-theme="xxx"] 下的 --* 变量。
常见错误是把 @themes 当成 JS 对象直接用在样式声明里,比如 color: @themes[light][primary];——Less 不允许这种运行时取值,必须配合 each() 转成 CSS 规则。
@themes 必须顶层声明,不能嵌套在 mixin 或选择器内light、dark、ocean),避免空格或特殊字符each(@themes, @theme, @name) 中的 @name 是主题名(light),@theme 是其子对象({ primary: #1890ff, ... })--theme-primary,避免和项目其他变量冲突示例片段:
@themes: {light: { primary: #1890ff; text: #333; bg: #fff; },dark:{ primary: #722ed1; text: #fff; bg: #1f1f1f; },ocean: { primary: #13c2c2; text: #262626; bg: #f8fbfb; }};each(@themes, .theme-rules);.theme-rules(@theme, @name) {:root[data-theme="@{name}"] {--theme-primary: @theme[primary];--theme-text: @theme[text];--theme-bg: @theme[bg];}}
如果你的主题变量用了 Less 内置函数(比如 lighten(@primary, 10%)、spin(@primary, 30)),或者复用了 antd 的 antd.less(v4),那默认 lessc 会报错:JavaScript evaluation not supported。这不是配置漏了,是编译器默认禁用 JS 执行。
容易被忽略的是:Node.js API 调用时也要显式传参,不是加个 --js 命令行就万事大吉。
lessc --js themes.less themes.css,少 --js 就失败less.render():options 里得有 { javascriptEnabled: true }
lessOptions 同样需要 javascriptEnabled: true,否则 modifyVars 覆盖后函数算不出来antd.variable.less 不依赖 JS 函数,但若你手动加了 mix() 或 contrast(),仍需开启搜“Less color-mix”常掉进坑里:color-mix(in srgb, var(--a), var(--b)) 是纯 CSS 运行时语法,Less 编译器不认识,直接报错 Operation on an invalid type。Less 能做的只有生成静态色值或导出变量供 CSS 使用。
真正可行的分工是:Less 算基础色,CSS 做混合。
@primary: #1890ff;,然后 --primary: @primary;
--primary-hover: color-mix(in srgb, var(--primary) 80%, #fff 20%);
in srgb,in lch 会静默失效,权重必须写全(不能省略 20%)color-mix() 前加一行硬编码 fallback:color: #1064b0;
很多人说“我写了 @color-primary,但在 button.less 里用不了”,检查后发现 variables.less 确实 @import 了——问题往往出在位置或嵌套上。
Less 没有全局变量池,变量作用域严格绑定导入顺序和声明位置。
@import 必须放在每个 .less 文件最顶部,不能在选择器、mixin 或注释之后.btn { @size: 14px; } 这种块级作用域里声明主题变量,它对外不可见@import 无效?那是 scoped style 独立编译,得用 style-resources-loader 或 Vite 的 vite-plugin-style-import 注入modifyVars 失效?先确认 variables.less 是否被主入口 @import 过,没引入就覆盖不了批量生成主题时,最稳的结构是:一个 themes.less(含 @themes 和 each()),一个 variables.less(只声明基础语义变量,如 @primary),所有组件文件顶部先 @import "variables.less",再 @import "themes.less"——顺序不能反。