颜色变量应按功能角色命名如$primary、$success而非视觉描述,避免语义锁定;推荐层级前缀如$color-primary;用Less .each()生成变体保持数学关系;主题切换需构建脚本配合,避免Less运行时响应;半透明状态须单独定义语义化变量。

颜色变量命名必须脱离视觉描述
直接用 red、light-blue 这类命名会锁死语义——当设计系统要求“主色从蓝色换成紫色”时,所有用到 $light-blue 的地方都得重查重改。真正可维护的做法是按功能角色命名:$primary、$success、$border-muted、$text-tertiary。
这些变量不表示“什么颜色”,而表示“在哪用、起什么作用”。实际色值可以后续通过主题文件覆盖,比如深色模式下 $text-tertiary 可能是 #999,浅色模式下是 #666,但业务组件里只认这个语义名。
- 避免:
$brand-blue、$hover-red - 推荐:
$primary、$state-error、$surface-card - 层级建议加前缀区分用途:
$color-primary、$color-text-primary,避免和间距/圆角等其他 token 冲突
用 Less map 实现颜色变体生成
手写 $primary-light、$primary-dark 容易遗漏或不一致。Less 本身不支持原生 map 遍历,但可用 .each() 混合(需 Less 4.0+)或预定义函数模拟:
.generate-color-variants(@name, @base) {
@<code>@{name}</code>: @base;
@<code>@{name}-light</code>: lighten(@base, 12%);
@<code>@{name}-dark</code>: darken(@base, 10%);
@<code>@{name}-contrast</code>: contrast(@base);
}
.generate-color-variants(primary, #007bff);
这样生成的 $primary、$primary-light 等变量保持数学关系,换主色时自动同步。注意 contrast() 返回的是黑白之一,适合文本反色场景;若需更精细控制明度,改用 mix(white, @base, 20%) 更可控。
立即学习“前端免费学习笔记(深入)”;
主题切换依赖 CSS 自定义属性时,Less 只负责编译期输出
如果项目用 document.documentElement.style.setProperty('--primary', '...') 动态切主题,Less 无法运行时响应。此时 Less 的职责是生成初始静态值,并导出为 JS 可读格式(如 JSON),或仅作为设计 Token 的源文件:
- 不要在 Less 里写
@media (prefers-color-scheme: dark)去覆盖变量——Less 编译完就没了 - 把基础色板抽成
colors.less,再由构建脚本读取它,生成 CSS 自定义属性或 JS 对象 - 若坚持纯 Less 方案,只能靠多入口编译:一个
light-theme.less,一个dark-theme.less,各自 import 同一套组件,但导入不同颜色配置
警惕透明度叠加导致语义失效
写 rgba($primary, 0.1) 看似方便,但一旦 $primary 变成深色系,rgba($primary, 0.1) 就可能变成不可见的灰雾。语义化颜色体系里,半透明状态应单独定义:
- 错误:
background-color: rgba($surface-card, 0.08); - 正确:
$surface-card-overlay: rgba(#fff, 0.08);(明确其用途是“浮层遮罩”,而非“表面卡的透明版”) - 更稳妥:用 HSL 调整亮度/饱和度代替 alpha,例如
hsla(hsl($primary), 0.12),至少保留色相一致性
颜色不是画笔,是接口。你暴露给组件的每个变量名,都在定义它能做什么、不能做什么——名字越具体,后期越少修修补补。


















