必须使用 :root 声明 CSS 变量,因其语义正确、跨文档兼容且优先级更高;变量名须双短横开头,引用时必须带 fallback 值,单位与数值不可分离,动态更新应通过 setProperty 修改 :root 样式。

在 :root 里声明 CSS 变量,不是 html 或 body
很多人写成 html { --color-primary: #007bff; },也能生效,但语义和作用域都不对。:root 是 CSS 规范定义的伪类,代表文档根元素(通常是 html),但它比直接写 html 多一层保障:在 SVG、XML 等非 HTML 文档中仍能正确匹配。更重要的是,:root 的优先级略高于 html,避免被意外覆盖。
常见错误现象:body { --color-primary: red; } 声明后,子元素用 color: var(--color-primary); 却没效果——因为变量没在继承链顶端声明,部分浏览器(尤其旧版 Safari)可能不向上查找。
- 必须用
:root,不要用html或body - 变量名必须以两个短横线开头,如
--spacing-md,不能是-spacing-md或spacing-md - 声明位置建议统一放在
<style></style>块顶部或单独的variables.css中,便于维护
var() 引用时 fallback 值不是可选的“锦上添花”,而是容错刚需
直接写 color: var(--color-primary); 很危险。一旦变量未定义、拼写错误、或被更高优先级规则重置为 unset,浏览器会回退到 inherited 值甚至 initial,结果不可控(比如文字突然变透明或黑得看不见)。
使用场景:主题切换、组件库提供默认值、CSS-in-JS 动态注入变量时网络延迟或 JS 错误导致变量未加载。
立即学习“前端免费学习笔记(深入)”;
- fallback 必须是合法 CSS 值,且与使用位置的属性兼容,例如
background-color: var(--bg, #fff);合法,font-size: var(--size, red);会失效 - 可以嵌套
var(),如var(--color-primary, var(--color-default, #333)),但别超过两层,可读性会崩 - 不要用
var(--missing)测试是否存在变量——它不会报错,只会静默失败
变量值带单位或函数时,不能拆开写,也不能在 calc() 外直接运算
CSS 变量存储的是“值”,不是“表达式”。写 --size: 16; --unit: px;,再用 font-size: var(--size) var(--unit); 是无效语法,浏览器直接忽略整条声明。
性能影响:错误写法会让样式引擎反复尝试解析,虽不卡顿,但 devtools 里会出现大量 invalid property 警告,干扰调试。
- 数值+单位必须一起存,如
--font-size-m: 1.125rem;或--space-xs: 4px; - 需要计算?用
calc()包裹,如padding: calc(var(--space-xs) * 2);(注意:只有加减乘除支持变量参与,且乘数/除数必须是数字) - 函数如
rgba()、url()可以整个作为变量值,如--logo: url(/logo.svg);,但不能把url(和)拆开存
动态更新变量要改 :root 元素本身,而不是重写样式表
想用 JS 切换主题色?别去操作 <style></style> 标签内容或插入新 <link>,那样触发重排重绘成本高,还容易冲突。
兼容性影响:IE 完全不支持 CSS 变量,所有现代浏览器(Chrome 49+、Firefox 31+、Safari 9.1+、Edge 15+)都支持,但 Safari 9.1–13.1 对 var() 在 @keyframes 里的支持有 bug,慎用。
- 用
document.documentElement.style.setProperty('--color-primary', '#28a745');最直接可靠 - 批量更新建议用
Object.entries(vars).forEach(([k, v]) => el.style.setProperty(k, v));,避免重复获取document.documentElement - 如果变量来自用户设置,记得用
CSS.escape()处理键名(虽然--开头基本安全),值则需自行校验合法性
变量作用域看似简单,但拼写错误、fallback 缺失、单位分离这三处,占了线上项目 80% 以上的相关 bug。真正难的不是“怎么写”,而是“怎么让别人(包括三个月后的你自己)一眼看懂哪条变量控制哪块颜色、间距或断点”。


















