根本原因是微信小程序WXML不支持原生CSS变量级联继承,:root声明无法穿透自定义组件且基础库2.25.2前存在var()解析缺陷,必须在每个组件.wxss中显式@import变量文件并确保单位一致、作用域可控。

小程序里为什么--color-primary不生效
根本原因是微信小程序的 WXML 不支持原生 CSS 变量的级联继承机制——:root 声明的变量无法穿透到自定义组件内部,且部分基础库版本(尤其是 2.25.2 之前)对 var() 的解析存在兼容性缺陷。
- 必须在每个组件的
.wxss文件中显式声明变量,不能只靠全局:root - 变量名带下划线(如
--bg_color)在旧版开发者工具中会被忽略,一律用连字符--bg-color -
var(--color, #000)的 fallback 仅在变量未定义时触发;若变量值为空字符串或initial,fallback 不生效 - 小程序不支持
@layer,所以变量作用域只能靠文件引入顺序和选择器权重控制
怎么让 var(--space-md) 在 button 和 card 里真正复用
关键不是“写一次变量”,而是让所有组件共用同一套变量源,并确保单位一致、计算安全。
- 把变量统一定义在
common.wxss中,所有页面和组件都@import "./common.wxss" - 避免在
calc()中混用单位:写padding: calc(var(--space-md) * 2)没问题,但calc(100% - var(--space-md))要求--space-md必须带单位(如16px),不能是纯数字 - 按钮和卡片各自声明局部变量更稳妥:
.btn { --btn-padding: var(--space-md); padding: var(--btn-padding); },避免跨组件直接读取根变量导致样式漂移 - 变量值尽量用相对单位(
rem或em)而非固定像素,适配不同屏幕密度
暗色模式切换时 document.documentElement.style.setProperty 为啥没反应
小程序没有 document.documentElement,JS 端操作 DOM 根节点无效;必须通过 setData 触发样式重载或使用 style 绑定动态 class。
- 正确做法:在页面 data 中定义
theme: 'light',WXML 中写class="{{theme}}-mode",WXSS 中写.light-mode { --text-color: #333; }和.dark-mode { --text-color: #fff; } - 如果要用 JS 动态改变量,得配合
getApp().globalData存储主题状态,并在每个组件 onShow 阶段重新 apply 样式 - 注意:
var(--text-color)在 WXSS 里不能用于@keyframes或伪元素content(除非内容是纯字符串且已加引号) - 小程序真机调试时,部分安卓机型对 CSS 变量更新有延迟,建议加
setTimeout(() => {}, 0)强制重绘
uni-app 项目里怎么避免原子类和自定义属性冲突
uni-app 编译成小程序后,class="p-4 text-primary" 这类原子类若也用了 var(--color-primary),就容易出现变量未定义却无报错、样式静默失效的问题。
立即学习“前端免费学习笔记(深入)”;
- 原子类的 CSS 必须放在
common.wxss最顶部,确保变量先于原子类被解析 - 禁止在原子类里嵌套
var()计算,例如.p-4 { padding: var(--space-md); }是安全的,但.p-4 { padding: calc(var(--space-md) * 2 + 1px); }在低版本基础库中会直接忽略整条规则 - uni-app 的
scoped样式会为选择器自动加属性前缀,导致:root变量无法被 scoped 内部读取,必须把变量声明移到非 scoped 的全局样式文件中 - 推荐组合策略:用自定义属性管「设计令牌」(颜色、圆角、断点),用原子类管「布局行为」(
flex、justify-center),二者职责分离
实际项目中最容易被忽略的,是变量作用域和小程序组件隔离模型之间的张力——你写的 --spacing-lg 在父页面生效,不代表它自动透传进子组件的 view 里。每次加新组件,都得确认它的 WXSS 是否 import 了变量源,而不是默认“全局可用”。


















