应在 :root 中定义全局 CSS 变量,如 :root { --theme-color: #4a6fa5; },变量名以 -- 开头,JS 通过 document.documentElement.style.setProperty 和 getComputedStyle(document.documentElement).getPropertyValue 安全读写,务必为 var() 提供 fallback。

怎么用 :root 定义全局 CSS 变量
CSS 变量必须先声明才能用,最稳妥的位置是 :root 伪类——它等价于 html 元素,但优先级更高、作用域更广,所有后代元素都能继承。
常见错误是直接在某个 class 里定义 --color-primary,结果 JS 找不到或覆盖失败;或者写成 var(--color-primary) 却漏了前面的 -- 前缀,浏览器直接忽略。
- 变量名必须以
--开头,比如--bg-color,不能是bg-color或$bg-color - 值可以是任意合法 CSS 值:
rgb(255, 99, 132)、1rem、bold,甚至另一个var(--base-font) - 推荐在
:root中设默认值,方便后续用 JS 覆盖::root { --theme-color: #4a6fa5; --border-radius: 8px; }
JS 怎么安全地读写 CSS 变量
核心是 getComputedStyle 和 style.setProperty,不是 document.style 或随便改 className —— 那样没法动态响应。
容易踩的坑:对非 :root 元素调用 getComputedStyle 只能读它自己声明的变量(不继承),而设变量时如果目标元素没挂载 style 属性,element.style.setProperty 会静默失败。
立即学习“前端免费学习笔记(深入)”;
- 读变量用:
getComputedStyle(document.documentElement).getPropertyValue('--theme-color')(注意带空格) - 写变量统一写到
document.documentElement.style,确保全局生效:document.documentElement.style.setProperty('--theme-color', '#ff6b6b') - 别用
setAttribute('style', ...)覆盖整个 style 字符串,会清掉其他内联样式
为什么 var(--x) 有时不生效
不是语法错,大概率是作用域或 fallback 没兜住。CSS 变量不支持“未定义就报错”,而是静默回退到初始值(通常是 inherit 或 initial),导致样式看起来“没变”。
典型场景:深色模式切换后背景还是白的、字体大小没缩放——其实是变量读到了空字符串或 unset,var(--size, 16px) 的 fallback 没写,或者写了但拼错了名字。
- 永远为
var()提供 fallback,比如font-size: var(--font-size, 16px) - 检查变量名是否大小写敏感(
--Color≠--color) - Chrome DevTools 的 Elements → Styles 面板里搜
--,能看到当前生效的变量值和来源
动态换肤时要注意的兼容性与性能点
CSS 变量本身兼容到 Chrome 49 / Firefox 31 / Safari 9.1,IE 完全不支持——如果要兼容 IE,得另配 class 切换方案,不能只靠变量。
性能上,频繁调用 setProperty 不会触发重排,但大量变量 + 复杂计算(比如用 calc(var(--a) * 2) 做响应式缩放)可能拖慢渲染,尤其低端安卓 WebView。
- 批量更新用
document.documentElement.style.cssText += '...'比多次setProperty略快,但可读性差,慎用 - 避免在
scroll或resize里实时算变量值,加防抖或用requestAnimationFrame - 主题切换建议存到
localStorage,页面加载时先设变量再渲染,防止闪屏
变量不是魔法,它只是把“哪边控制样式”的决定权交给了 JS;真正难的是变量命名一致性、fallback 设计、以及和现有 class 体系怎么共存——这些没法靠一行 setProperty 解决。


















