颜色变量应按语义层级命名(如--color-text-primary),绑定设计系统角色而非物理值;物理值仅存于底层token,深色模式通过prefers-color-scheme自动切换;fallback须为同语义变量,禁用calc()混色与rgb函数,color-mix()须保留在runtime执行。

颜色变量命名要能反映语义层级,不是物理值
很多人一上来就用 $blue-500 或 --primary-hex 命名 CSS 变量,结果组件换肤时全得重写。真正该暴露的是用途,比如 --color-text-primary、--color-surface-card,而不是蓝不蓝、#3b82f6 不是 #2563eb。
- 语义名绑定设计系统角色(text / border / surface / accent),不是色卡编号
- 物理值(如 HSL 分量、HEX)只藏在最底层 token 文件里,业务组件绝不直接读取
- 同一语义名在深色模式下应自动映射到另一组物理值,靠 CSS @media 或 prefers-color-scheme 切换,不是 JS 注入新变量
CSS 自定义属性的 fallback 必须可运行,不能留空
写 color: var(--color-text-primary, #1f2937) 看似稳妥,但万一 --color-text-primary 被误删或未注入,fallback 会硬编码进所有组件样式,失去主题动态能力。更糟的是,某些构建工具会提前内联 fallback,导致深色模式失效。
- fallback 值应是同语义的兜底变量,例如
var(--color-text-primary, var(--color-text-default)) - 顶层变量(如
--color-text-default)才允许设物理值,且必须有完整色阶(light/dark/high-contrast)三套 - 用
@supports (color: oklch(0 0 0))测试新色彩空间支持时,fallback 也要对应 OKLCH 表达式,别混用 HEX
组件内避免用 calc() 混合主题色,尤其别碰 opacity
看到 background: color-mix(in srgb, var(--color-accent) 70%, white 30%) 就该警觉——这不是“灵活”,是把主题逻辑泄漏到组件层。一旦设计规范要求 accent 色在深色模式下变饱和度更高,所有用了 color-mix 的地方都得手动改。
- 所有明暗/透明/叠加效果,统一收口到 token 层,提供
--color-accent-subtle、--color-accent-hover等预计算变量 - 禁止在组件 CSS 里写
rgba(var(--color-accent-rgb), 0.1),RGB 函数在旧浏览器不兼容,且无法被 CSSOM 读取用于 JS 动态调整 - 需要动态亮度的场景(如按钮按压反馈),用
color-adjust: economy+ 单独 hover 变量,比 runtime 计算更可控
PostCSS 插件处理色值转换时,别绕过 CSS 自定义属性解析链
用 postcss-color-function 或 postcss-preset-env 支持 color-mix() 很方便,但如果插件在自定义属性赋值阶段就展开(比如把 --color-bg: color-mix(...) 编译成 --color-bg: #f9fafb),整个主题切换机制就废了——JS 再怎么切换 :root 变量,编译后都是死值。
立即学习“前端免费学习笔记(深入)”;
- 确保插件配置中
preserve: true开启,让 color 函数保留在 runtime 执行 - 避免在 :root 块外使用
color-mix(),部分浏览器对嵌套作用域里的函数解析不稳定 - CI 中加一条检查:grep -r "color-mix" src/ | grep -v ":root" —— 出现就报错










