Less 通过编译期变量替换实现主题切换,需统一管理变量于 variables.less 并禁用组件内重定义;利用 less-loader 的 modifyVars 动态覆盖变量,比 CSS 变量或媒体查询更可靠、高效且 SSR 友好。

因为 Less 的变量和 @import 机制能实现「编译期主题切换」,而原生 CSS 变量(var(--color))必须靠 JS 运行时注入或手动切类名,两者根本不在同一工程层级上。
深色模式变量必须收口到单一 variables.less 文件
Less 不支持运行时换主题,但能靠编译时条件生成两套 CSS:一套 light,一套 dark。前提是所有颜色、背景、边框值都来自 base/variables.less,且只被根文件 index.less 导入一次。否则会出现:@bg-color 在 button.less 里是 #fff,在 card.less 里却是 #f5f5f5 —— 这不是主题,是漂移。
- 禁止在组件文件里重定义同名变量,比如
@bg-color: #1a1a1a;;要加后缀,如@bg-color-dark - CI 流程中加校验:
grep -r "@bg-color" src/ | grep -v "base/variables.less",有输出就阻断合并 - 深色变量命名建议带语义:
@text-primary-dark而非@text-dark,避免和@text-secondary-dark混淆
less-loader 的 modifyVars 是主题切换的真正开关
Next.js 或 webpack 项目里,不用写两套 .less 文件,靠 less-loader 的 modifyVars 参数就能动态覆盖变量值。比如构建深色包时传入:
modifyVars: {
'@bg-color': '#121212',
'@text-primary': '#e0e0e0',
'@border-color': '#333'
}
这比原生方案里用 JS 切 document.documentElement.classList.add('dark') 更干净——它不依赖 DOM 状态,也不怕 SSR 时首屏闪白。
- 不能用
globalVars,它只支持字符串字面量,无法处理颜色函数如lighten(@primary-color, 10%) -
modifyVars会覆盖variables.less中的原始赋值,顺序无关,但必须确保被编译器读到 - 如果用了
@import (multiple),变量可能被重复覆盖,某些 less 版本会静默取最后一次值
嵌套 + & + 媒体查询无法替代主题变量切换
有人试图用原生 CSS 嵌套 + @media (prefers-color-scheme: dark) 实现深色模式,但在 Less 里这反而会制造维护黑洞:
- 每个组件都要写一遍
@media (prefers-color-scheme: dark) { & { ... } },复用率归零 - 嵌套层级过深时,
&行为不可控,比如.card:hover &__title在媒体查询里可能错位匹配 - prefers-color-scheme 不是全平台可靠:iOS Safari 对强制深色适配差,Windows Electron 默认不触发
- Less 编译后输出的是纯 CSS,
@media规则仍存在,但变量替换已固化——你拿到的是确定的深色 CSS,不是一堆待求值的var()
真正卡住效率的不是写代码,而是改一处深色值后,得翻 17 个文件确认有没有漏掉 @import、有没有变量拼错、有没有被 @import (multiple) 覆盖了——这些事 Less 编译器不会报错,只会静默失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











