所有全局css变量必须声明在:root中,否则无法被全页面稳定读取;局部覆盖仅限深色模式等场景,通过html类名切换;fallback必须为合法css字面量且数值带单位;间距字号应绑定基础单位变量并用calc计算;命名需语义化分层,避免作用域污染。

所有全局变量必须声明在 :root 中
写在 .button、.card 或媒体查询里定义 --color-primary,等于主动放弃复用能力。浏览器按 DOM 继承链向上查找变量,:root 等价于 html 元素,是唯一能被全页面所有选择器稳定读取的作用域。
常见错误现象:.header { --text: #333; } 后,.button { color: var(--text); } 读不到,文字变成黑色(回退到初始值),控制台无报错,Computed 面板显示 color: initial。
-
:root是起点,不是可选项;其他地方只允许var(--x)引用 - 需要局部覆盖(如深色模式)?加 class:
html.theme-dark { --bg: #1e1e1e; },别在组件内重写 - PostCSS 插件(如
postcss-css-variables)无法跨@import解析变量,构建时报Error: Cannot resolve variable --text—— 手动合并或改用 JS 注入
var() 的 fallback 必须是合法字面量
color: var(--text-color, var(--fallback)) 这种写法会让浏览器把第二层 var() 当作纯字符串渲染,最终页面文字直接消失,Computed 值里显示 "var(--fallback)",控制台不报错,极难定位。
正确 fallback 只有两种安全方式:
-
color: #333; color: var(--text-color, #333);(先写降级,再覆盖) -
color: var(--text-color, #666);(单层,值为合法 CSS 字面量) - 数值类 fallback 必须带单位:
font-size: var(--size, 16px)✅,font-size: var(--size, 16)❌
间距、字号等数值类变量必须绑定基础单位
硬编码一堆 .mt-1 { margin-top: 0.25rem; }、.mt-2 { margin-top: 0.5rem; },只是把重复从值转移到类名上。后期想把基础单位从 0.25rem 调成 0.3rem,就得手动改二十个类。
实操建议:
- 在
:root定义--space-unit: 0.25rem; - 工具类用
calc(var(--space-unit) * 4)生成倍数,例如.mt-4 { margin-top: calc(var(--space-unit) * 4); } - 字号响应式别靠媒体查询改
:root变量——它不会触发重计算;改用clamp(14px, var(--font-size-base), 18px)
变量命名和层级设计比声明本身更关键
起名 --primary 看似省事,但项目一复杂,--primary 到底指品牌色、按钮背景、还是链接文字?没人敢动。真正难的不是写几个 --x,而是建立清晰层级:
- 语义分层示例:
--color-brand-primary(品牌主色)、--color-ui-accent(交互强调色)、--color-text-default(正文默认色) - 避免作用域泄漏:不要在组件内部定义同名变量(如
.card { --bg: #fff; }),否则会污染后代且无法被外部感知 - JS 动态修改高频触发重排:用
document.documentElement.style.setProperty('--x', 'y')没问题,但每帧都调用会导致性能抖动
守住 :root 这条线,变量才真正“活”得起来——所有定义从这里出发,所有引用只靠 var() 拉取,中间不插手、不绕路、不妥协。一旦变量在非 :root 处被重写,它就全局生效,且没有“回退”机制。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











