小程序主题色必须通过theme.json预设+class切换实现,因不支持document操作和运行时CSS变量修改,需结合uni.setAppTheme控制原生样式、预设CSS类控制组件样式。

小程序端主题色不能靠 document.documentElement.style.setProperty
直接用 window.document.documentElement.style.setProperty 设置 CSS 变量,在微信小程序里会报错:找不到 window 或 document。因为小程序运行在封闭的 JS 引擎(不是浏览器),没有 DOM API。这是最常踩的坑——本地 H5 跑通了,一真机就白屏或样式不生效。
实操建议:
- 别写
document.documentElement.style.setProperty('--primary', '#007aff') - 所有颜色变量必须通过
uni.scss预编译注入,或用style绑定 + class 切换 - 如果后端返回主题色(如
{"primary": "#ff6b35"}),得转成uni.scss可识别的格式,再重新编译 —— 但 runtime 不支持重编译,所以只能走「预置多套主题 + 动态切换 class」路线
theme.json 是小程序端唯一可靠的全局主题配置入口
小程序平台(含微信、支付宝等)只认 theme.json 定义的变量,且必须配合 pages.json 中的 @xxx 语法使用。它不是 CSS 变量,而是 uni-app 编译期解析的占位符,能控制导航栏、tabBar、页面背景色等原生级样式。
常见错误现象:
- 写了
theme.json但pages.json没加@前缀 → 样式不变 - 在组件内写
background-color: @primary→ 编译报错,@只能在pages.json里用 - 把深色模式逻辑全塞进
theme.json,却没调用uni.setAppTheme({ theme: 'dark' })→ 系统不触发切换
正确做法:
- 根目录建
theme.json,定义light和dark对象,字段名如navBgColor、tabBarBg -
pages.json全局或页面级 style 中写"navigationBarBackgroundColor": "@navBgColor" - 调用
uni.setAppTheme触发切换,注意该 API 在小程序端仅支持light/dark,不支持auto
组件内动态主题色必须用 class + CSS 变量组合
小程序不支持运行时修改 :root 的 CSS 变量,也不支持 v-bind 动态绑定样式属性(如 :style="{ color: theme.primary }")。想让按钮、卡片等响应主题变化,只能靠 class 切换 + 预设 CSS 变量。
实操建议:
- 在
uni.scss里定义两套变量:$theme-light-primary: #007aff和$theme-dark-primary: #0a84ff - 写两个 class:
.theme-light { --primary: #007aff; }和.theme-dark { --primary: #0a84ff; } - 根节点(如
<view class="theme-{{ currentTheme }}">)绑定当前主题 class - 组件内统一用
color: var(--primary),不要硬写color: $theme-light-primary
注意:小程序基础库低于 2.25.2 时,var(--x) 支持不稳定,建议最低兼容版本设为 2.27.0+
接口下发的主题色怎么落地到小程序?
后台下发的动态主题色(比如节日皮肤 {"bg": "#ffeb3b", "btn": "#e65100"})无法直接注入 theme.json,也不能改 uni.scss。唯一可行路径是:把接口数据映射到预设的有限主题 slot 中,再触发 class 切换。
例如:
- 前端预置 3 套主题:
default、festival、brand,每套对应完整 CSS 变量集 - 接口返回
themeKey: "festival",前端存入uni.setStorageSync('activeTheme', 'festival') - 所有页面
onLoad时读取并设置根节点 class:this.themeClass = 'theme-' + uni.getStorageSync('activeTheme') - 避免在
watch或computed里反复读 storage —— 小程序 setData 频繁触发会导致卡顿
真正难的不是换色,而是保证「页面打开瞬间就是目标主题」。小程序页面初始化早于 onLoad,所以必须用 theme.json + setAppTheme 控制原生层,再用 class 控制组件层,二者缺一不可。


















