css变量应统一在:root定义,用功能名(如--color-primary)和hsl格式存储,通过calc()派生明暗色,主题切换仅替换data-theme类,js须用getcomputedstyle动态读取。

用 :root 定义基础色值,别在每个选择器里重复写颜色
直接在 :root 里声明 CSS 变量,是复用和批量调整配色的唯一靠谱起点。写在其他选择器里(比如 .btn { --primary: #007bff; })会导致变量作用域碎片化,改个主色得翻十处文件。
常见错误:把变量名起成 --blue-500 这类语义模糊的命名,结果换设计稿时发现“500”根本对不上新规范;或者混用 HEX 和 HSL,后期调亮度/饱和度时完全没法批量算。
- 用功能名命名:
--color-primary、--color-success、--color-border-subtle - 统一用 HSL 表示(如
hsl(210, 100%, 50%)),方便后续用hsl(var(--h), var(--s), calc(var(--l) - 10%))派生深浅色 - 避免在
:root里写带单位的值(比如--space-md: 1.25rem可以,但--color-bg: rgba(0,0,0,0.04)不推荐——透明度应单独抽为--alpha-overlay)
用 hsl() + CSS 变量做明暗梯度,别手写一串 HEX
手动列 #0066cc、#0055aa、#004488 看似省事,实际维护成本爆炸:UI 改个主色饱和度,你得重算全部;夜间模式切换时更没法动态响应。
HSL 的优势在于 hue(色相)可独立控制,lightness(明度)能线性调节。只要基础色定义为 hsl(220, 90%, 55%),就能用 hsl(220, 90%, 40%) 和 hsl(220, 90%, 70%) 快速生成深浅变体。
- 基础色变量只存 hue/saturation/lightness 三个数字:
--h-primary: 220; --s-primary: 90%; --l-primary: 55%; - 派生色直接组合:
background-color: hsl(var(--h-primary), var(--s-primary), calc(var(--l-primary) - 15%)); - 注意:Safari 15.4 之前不支持在
hsl()里嵌套calc(),需降级 fallback(如先定义--l-primary-dark: 40%;)
主题切换时只换变量值,别用 @media (prefers-color-scheme) 写两套色板
@media (prefers-color-scheme: dark) 适合处理系统级自动切换,但业务中更多是手动切主题(比如右上角点一下“深色模式”)。这时候如果每套主题都写一遍完整变量,等于把重复逻辑从 CSS 里搬回 JS 控制层,失去变量抽象意义。
正确做法是让 JS 只负责切换一个 class(如 html[data-theme="dark"]),所有颜色计算仍在 CSS 内完成。
- 在
:root里定义默认值:--color-bg: #fff; --color-text: #333; - 用属性选择器覆盖:
html[data-theme="dark"] { --color-bg: #1a1a1a; --color-text: #e0e0e0; } - 禁止在 JS 里直接操作
document.documentElement.style.setProperty('--color-bg', '#1a1a1a')—— 这会让 CSS 变量变成内联样式,优先级失控,且无法被 :root 中的 calc() 引用
导出变量到 JS 时用 getComputedStyle,别硬编码字符串
前端组件需要读取主色做 canvas 绘图或 SVG 填充时,有人会直接在 JS 里写 const primary = '#007bff';,结果设计改色后漏同步,图表颜色就和按钮对不上。
CSS 变量本质是运行时值,JS 应该实时取,而不是静态复制。尤其当变量本身含 calc() 或依赖父级 font-size 时,硬编码必错。
- 安全读法:
getComputedStyle(document.documentElement).getPropertyValue('--color-primary').trim() - 注意返回值带空格,且 HSL 格式是
"hsl(210, 100%, 50%)",不是数字数组,需自行解析 - 别用
document.body.style.getPropertyValue—— body 上没定义变量,永远返回空字符串
最麻烦的其实是灰色系:它既要适配不同背景的可访问性对比度,又得在 light/dark 主题下保持视觉重量一致。这时候单靠一套 --color-gray-300 不够,得按用途拆成 --color-gray-bg、--color-gray-border、--color-gray-text-secondary,各自在不同主题下设不同 HSL lightness —— 少了这层区分,WCAG 对比度检测准会报错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











