web学习笔记编程技术学习与分享
首页 / 前端开发 / 正文

CSS 变量与设计令牌:让主题切换变简单

2026 年 08 月 30 日约 3 分钟阅读 前端开发

把颜色、圆角、间距抽成 CSS 自定义属性,是前端工程里性价比最高的一次重构。它不需要构建工具,浏览器原生支持,而且可以在运行时改变。

变量是继承的

--name 定义在哪个元素上,就作用于该元素及其子树。所以把令牌放在 :root 上就是全局变量,放在某个容器上就是局部变量。

:root {
  --brand: #2b5cff;
  --bg: #ffffff;
  --ink: #101828;
  --line: #e6e9f0;
  --radius: 12px;
}

.card {
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

主题切换的两种方式

第一种是给 <html> 加 data-theme 属性,用属性选择器覆盖变量:

[data-theme="dark"] {
  --bg: #0f1419;
  --ink: #e6e9ef;
  --line: #232a35;
}

第二种是用 prefers-color-scheme 跟随系统。两者可以组合:默认跟随系统,用户手动切换后写 data-theme 覆盖。

const saved = localStorage.getItem('theme');
if (saved) document.documentElement.dataset.theme = saved;

注意:主题状态存 localStorage 是「界面偏好」,不属于用户数据,刷新后需要立刻恢复,所以要在 <head> 里尽早执行,避免白屏闪烁(FOUC)。

变量也能参与计算

自定义属性本身是字符串,但配合 calc() 可以写相对值:

:root { --gap: 8px; }
.grid { gap: calc(var(--gap) * 2); }

需要注意,calc() 里的变量必须带单位。如果希望变量是纯数字再乘单位,要用 calc(var(--n) * 1px) 这种写法,或者用新的 @property 声明类型。

什么时候不该用变量

不是所有值都值得抽成变量。只用一次的颜色、一次性的定位偏移,直接写在规则里更清晰。判断标准是:这个值是否需要在多处保持一致,或者需要被运行时改变。两个条件都不满足时,抽象只会增加阅读成本。

CSS主题工程化