小程序端css变量必须定义在:root或html下才全局生效,正确做法是新建static/css/variables.css并由main.js导入,pages.json的globalstyle与css变量无关,动态主题应使用data-theme属性而非setproperty。

小程序端 CSS 变量必须定义在 :root 或 html 下才真正全局生效
直接在 App.vue 的 <style scoped></style> 里写 :root { --color-primary: #007AFF; },H5 可能看起来有效,但微信/支付宝小程序会忽略——因为 scoped style 被编译器隔离,:root 作用域不被识别。
正确做法是:新建 static/css/variables.css,内容只写:
:root {
--color-primary: #007AFF;
--font-size-base: 14px;
}
然后在 main.js 顶部导入:
import '@/static/css/variables.css'
注意:@/App.vue 里不要 import 这个文件,也不要把它塞进 <style></style> 块里;否则小程序构建时可能丢掉或作用域失效。
pages.json 的 globalStyle 不是 CSS 变量,别混用
globalStyle 是原生窗口配置项,只影响导航栏、背景色等系统级样式,不能定义 --xxx 这类可在组件内 var(--xxx) 引用的 CSS 变量。
常见错误:
- 在
pages.json里写"--color-primary": "#007AFF"—— 无效,JSON 不解析 CSS 语法 - 以为
globalStyle.backgroundColor能被 JS 读取为getComputedStyle(document.documentElement).getPropertyValue('--bg')—— 完全无关
它和 CSS 变量是两条平行线:一个控制原生容器,一个控制 Web 渲染层。
小程序平台对 CSS 变量的硬限制必须绕开
微信小程序基础库 getComputedStyle(el).getPropertyValue('--x') 返回空字符串;安卓部分 WebView 会忽略 document.documentElement.style.setProperty() 动态设置。
实操建议:
- 静态变量(主题色、字号)全靠
static/css/variables.css+main.js导入,避免运行时 setProperty - 需要动态切换主题?改用
document.documentElement.setAttribute('data-theme', 'dark'),再配合 CSS 层级:[data-theme="dark"] .btn { background: var(--color-bg); } - 不要在
@keyframes或多层calc(var(--a) + var(--b))里嵌套 CSS 变量——小程序渲染引擎不支持
Scss 变量和 CSS 变量不能互相替代,尤其在小程序里
你在 uni.scss 或 variables.scss 里写的 $primary-color 是编译期常量,打包后就变成死值;而 --color-primary 是运行时可被 JS 修改的活变量。
所以:
- 换肤、夜间模式、用户偏好设置 → 必须用 CSS 变量(
--xxx),且走:root+static/css/variables.css路径 - 项目中固定不变的设计 token(比如按钮圆角、标准间距)→ 可用 Scss 变量,但需通过
vite.config.ts的css.preprocessorOptions.scss.additionalData注入,写法是:@use "@/styles/vars.scss" as *; - 千万别在 Scss 文件里写
--color-primary: #007AFF当成 CSS 变量用——它只是普通属性声明,不会注册为 CSS 自定义属性
最易忽略的点:小程序真机调试时,热更新可能让 CSS 变量注入延迟半秒,导致首屏样式闪动。上线前务必在真机上验证 static/css/variables.css 是否随 main.js 同步加载完成。











