必须将所有设计系统变量统一写在 :root 中,因其是 css 规范唯一指定的全局锚点,确保强制继承、高特异性及 shadow dom/ssr 兼容性;应放语义化颜色、基础间距、字体基准等通用 token,不放组件级样式或需 js 动态计算的值;主题切换须用 data-theme 属性控制,fallback 必须写实,var() 失效主因是拼写错误、声明顺序错或值非法。

必须把所有设计系统变量统一写在 :root 里,否则颜色、间距、字体这些值会散落各处,后期改一个主题色就得全局搜替换——这是最直接的维护灾难。
为什么只能用 :root,不能用 html 或 body
浏览器对 :root 的处理是强制继承:所有元素默认从它继承自定义属性。而 html { --color-primary: #007bff; } 虽然能用,但在 Shadow DOM、all: unset 元素或某些 SSR 场景下会断继承;body 更糟——子元素不显式继承就拿不到变量。:root 是 CSS 规范唯一指定的“全局锚点”,特异性(0,1,0)也比 html(0,0,1)略高,冲突时更稳。
:root 里该放什么,不该放什么
适合放的:
- 语义化颜色:
--color-primary、--color-surface、--color-text - 基础间距单位:
--spacing-xs(4px)、--spacing-md(16px),配合calc()构建弹性系统 - 字体基准:
--font-size-base(16px)、--line-height-base(1.5) - 圆角/阴影等设计 token:
--radius-sm、--shadow-md
不该放的:
- 组件级样式值(如
--button-padding),这类应由组件自身定义 - 需要 JS 实时计算的动态值(比如视口宽度百分比),CSS 变量不响应 resize,得用 JS +
style.setProperty - 带单位的复合表达式(如
--size: 1rem * 2),CSS 不支持运算,得写成--size: 2rem或用calc(var(--unit) * 2)
主题切换必须用 data-theme,别信 @media (prefers-color-scheme) 单独生效
单纯靠媒体查询写 @media (prefers-color-scheme: dark) { :root { --color-bg: #1a1a1a; } } 有两大问题:首次渲染可能取错值;和用户手动切换的主题冲突。正确做法是收口到 data-theme 属性:
- 定义多个
:root[data-theme="dark"]、:root[data-theme="blue"]块,只覆盖需要变的变量 - JS 切换时用
document.documentElement.setAttribute('data-theme', 'dark'),别用className替换,避免清掉其他 class - fallback 必须写实:比如
background-color: var(--color-surface, #ffffff),否则变量未定义时样式会崩
var() 失效的三个高频原因
不是语法错,而是作用域或时机问题:
- 变量名拼错或大小写不一致:
--ColorPrimary和--color-primary是两个变量 - 变量声明位置被后续 CSS 覆盖:确保
:root块在样式表靠前加载,或至少在使用它的规则之前 - 值本身无效:比如
--size: 12缺单位,或--color: #ggg颜色非法,都会触发 fallback,但你可能没意识到变量本身错了
真正在意一致性的人,会在开发期打开 DevTools 的 “Computed” 面板,挨个检查 var(--xxx) 是否解析出预期值——这比写一百行注释都管用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











