必须用:root声明全局css变量,因其是css规范指定的文档根作用域锚点,特异性更高(0-1-0)、跨文档兼容(svg/xml有效)、继承可靠;html或body声明易被覆盖或无法向上继承。

直接用 :root 声明带语义前缀的 CSS 变量,就能在 Web、Weex、ILLA Builder、AList 等跨平台项目中复用同一套颜色/间距/字体值——前提是变量声明位置正确、单位明确、不混用预处理器变量。
为什么 :root 是唯一可靠的作用域起点
CSS 变量靠继承传播,:root 是 HTML 文档的根,所有元素默认继承其变量。漏写或写成 html、body、组件级 div 都会导致子组件拿不到值,尤其在 Shadow DOM 或 Vue/React 的 scoped style 里更明显。
-
:root下定义:--color-primary: #007bff;→ 全局可读 -
.theme-wrapper { --color-primary: #007bff; }→ 仅该元素及其后代能访问 - 在 SCSS 文件里写
$primary: #007bff;再试图--color: $primary→ 编译后消失,运行时无效
var() 使用时单位和拼写必须严格匹配
变量值里带单位(如 --space-md: 16px;),调用时就不能再加单位;无单位值(如 --line-height-base: 1.5;)则不能补 px/em。拼错变量名会静默 fallback 到 inherit 或初始值,很难排查。
- ✅ 正确:
padding: var(--space-md) var(--space-lg); - ❌ 错误:
font-size: var(--font-size-base)px;(重复单位) - ❌ 错误:
color: var(--color-prime);(拼写错误,无报错但无效) - ⚠️ 注意:Vue/React 动态注入时,
style={{ '--space-md': 16 }}必须手动加单位,写成'16px'
主题切换别只改变量,得同步控制作用域类名
单纯用 document.documentElement.style.setProperty('--bg', '#1a1a1a') 能生效,但无法触发 CSS 中基于类名的条件覆盖(比如深色模式下图标反色、禁用态透明度调整)。真正可靠的方案是切 class,让 CSS 规则批量接管。
- 定义两套变量:
:root { --bg: #fff; }和:root.dark-theme { --bg: #1a1a1a; } - 切换时操作 class:
document.documentElement.classList.toggle('dark-theme') - 避免只改变量 + JS 逻辑分散管理样式状态,否则 SSR 首屏渲染会不一致
别在 calc() 里对未计算的变量做运算
calc(var(--space-md) * 2) 在所有浏览器都无效——CSS 不支持运行时算术运算符作用于变量。它不会报错,但解析结果是 calc(invalid * 2),最终 fallback 到默认值。
- ✅ 提前算好:
--space-xl: 32px;(而不是依赖乘法) - ✅ 或用构建时工具(如 PostCSS 插件)展开计算,生成静态值
- ⚠️ 注意:Weex 和部分老版 WebView 对
calc()支持有限,连基础calc(100% - 20px)都可能出问题
真正难的不是定义变量,而是确保每个平台加载顺序、作用域、单位、主题类名切换全部对齐——少一个环节,跨平台一致性就断在那个点上。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











