CSS变量是解决样式重复维护的根本手段,需用:root定义、var()配默认值、calc()参与运算,并坚持统一命名与按需引入。

CSS变量不是“锦上添花”,而是解决重复改色、改间距、切主题时反复搜索替换的根本手段。它原生支持、无需编译、可被JavaScript读写,只要用对作用域和var()的默认值机制,就能立刻减少50%以上样式维护成本。
定义全局变量必须用 :root,别写成 html 或 body
很多人图省事把变量写在html或body里,结果子元素拿不到——CSS变量的作用域遵循标准继承规则,只有:root(等价于html但语义明确且兼容性更稳)能保证真正全局可访问。
-
:root是唯一被规范明确定义为“文档根”的伪类,所有浏览器都把它当作变量全局作用域锚点 - 写
html { --color-primary: #007bff; }在部分旧版 Safari 中会失效 - 变量名必须以
--开头,比如--spacing-md,不能省略或写成_或$ - 值可以是任意合法 CSS 值:
--line-height: 1.5、--shadow: 0 2px 4px rgba(0,0,0,0.1)、甚至--icon-url: url(/icons/check.svg)
var() 必须配默认值,否则变量未定义时样式直接崩
当你在组件中引用var(--color-bg),而这个变量还没被定义(比如主题CSS还没加载完,或局部覆盖漏写了),浏览器不会 fallback 到继承值,而是直接丢弃整条声明——background-color: var(--color-bg); 这行就等于没写。
- 永远用
var(--color-bg, #fff)这种带默认值的写法,尤其在关键视觉属性上 - 默认值不只能是字面量,还能是另一个
var()调用:var(--color-bg, var(--color-surface, #fff)) - 不要依赖“反正我全局定义了”,组件库、微前端、CSS-in-JS 环境下变量极易缺失
- 调试时可临时加
outline: 1px solid red确认某条var()是否生效,比查控制台 computed 更快
用 calc() 和 CSS 变量组合做响应式尺寸,别再写媒体查询堆砌
固定font-size: 16px + 大量@media调整,不如用变量存基准值,再用calc()动态算。这样改一个数,所有相关尺寸自动响应,而且逻辑集中、无冗余。
立即学习“前端免费学习笔记(深入)”;
- 例如:
:root { --fs-base: 16px; --scale-ratio: 1.125; },然后h2 { font-size: calc(var(--fs-base) * var(--scale-ratio)); } -
calc()支持单位混合:width: calc(100% - var(--spacing-md) * 2)合法且常用 - 注意空格:
calc(100%-var(--spacing-md))(无空格)会报错,必须写成calc(100% - var(--spacing-md)) - 变量本身不能直接参与运算(如
--fs-base * 2非法),必须套calc(),这是初学者最常卡住的地方
引入 Open Props 这类变量库时,只导入需要的模块,别全量 @import
Open Props 提供colors、shadows、spacing等独立模块,全量引入不仅增加体积,还会污染你的变量命名空间,比如--shadow-soft和你自定义的--shadow-card容易混淆。
- 推荐按需导入:
@import "open-props/colors"; @import "open-props/spacing"; - 若项目已用 PostCSS,可通过插件自动提取未使用的变量,避免“定义了但从不引用”的隐性膨胀
- 变量名前缀统一很重要:Open Props 用
--color-,你自己定义就别混用--c-或--clr-,团队协作时一眼能分清来源 - 上线前用
grep --include="*.css" -r "--my-var" .快速检查变量是否真被引用,避免“定义即负债”
真正难的不是学会怎么写--xxx和var(),而是坚持让每个颜色、每个间距、每个圆角都走变量路径——哪怕只是临时改个按钮背景,也先去:root里找有没有现成变量,没有就加一个。这种习惯一旦建立,后续所有主题切换、设计系统升级、夜间模式落地,就只是改几行:root的事。


















