Skip to content

VaporCSS 主题适配

UniApp X 官方主题系统

适用版本:HBuilder X 4.18+

完整主题适配教程详见官方文档。本文仅讲解 theme.json 的用法,用于解决 pages.json 的主题适配问题。

为什么需要 theme.json

当应用需要暗黑主题时,开发者虽然可以自行决定自己的界面样式,但缺少合适的设置 pages.json 中样式的时机。

在页面的 onLoad 中设置当前页面的样式会来不及,因为某些平台页面早于 onLoad 就可以创建和进行窗体转场动画,这会造成新页面动画刚开始时页面的背景色、navigationBar背景色是一个风格,而在 onLoad 后颜色发生变化。

也就是俗称的 转场闪白闪黑

小程序提供了 theme.json 来解决这个问题。在 theme.json 里配置 lightdark 的颜色,然后在 pages.json 中引用。

新页面创建时是根据 pages.json 的设置来初始化页面的,这样就可以在第一时间对页面样式进行适配,避免闪白闪黑。

考虑到全端兼容,UniApp X 的 web 和 app 也支持 theme.json 设置。

注意theme.json 仅负责 pages.json 的页面样式、tabbar样式的控制,不负责开发者自己的页面css样式控制。

适配暗黑模式相关API

除通过 theme.json 控制 pages.json 的样式外,还需要了解以下API:

获取OS/Host主题:

  • uni.getSystemInfouni.getDevideInfo,返回的 osThemehostTheme 属性

监听OS主题切换:

  • uni.onOsThemeChangeuni.offOsThemeChange

监听host主题切换:

  • uni.onHostThemeChangeuni.offHostThemeChange

获取App主题:

  • uni.getSystemInfouni.getAppBaseInfo,返回的 appTheme 属性

设置App主题:

  • uni.setAppTheme

监听App主题切换:

  • uni.onAppThemeChangeuni.offAppThemeChange

manifest.json中设置App默认主题:

  • "defaultAppTheme": "light",支持通过主题API动态设置

theme.json 使用步骤

  1. 在项目根目录下创建 theme.json
  2. theme.json 中定义相关变量
  3. pages.json 中以 @ 开头引用变量
  4. 可选在 manifest.json -> app 中配置主题默认值

theme.json 内容描述

theme.json 用于颜色主题相关的变量定义,包含以下属性:

属性类型必填描述
lightObject浅色模式下的变量定义
darkObject深色模式下的变量定义

示例配置

json
{
  "light": {
    "navBgColor": "#f8f8f8",
    "navTxtStyle": "black"
  },
  "dark": {
    "navBgColor": "#292929",
    "navTxtStyle": "white"
  }
}

在 pages.json 中引用变量

完成定义后,可在 pages.json 中全局配置或页面配置的相关属性中以 @ 开头引用:

json
// 全局配置
{
  "globalStyle": {
    "navigationBarBackgroundColor": "@navBgColor",
    "navigationBarTextStyle": "@navTxtStyle"
  }
}

// 页面配置
{
  "path": "pages/index/index",
  "style": {
    "navigationBarBackgroundColor": "@navBgColor",
    "navigationBarTextStyle": "@navTxtStyle"
  }
}

支持的配置项

pages.json 中并非所有配置项均支持使用 theme.json 中的变量,支持通过变量配置的属性如下:

全局配置 globalStyle 与页面 style 支持:

  • navigationBarBackgroundColor
  • navigationBarTextStyle
  • backgroundColor
  • backgroundTextStyle

全局配置 tabbar 属性:

  • color
  • selectedColor
  • backgroundColor
  • borderStyle
  • list
  • iconPath
  • selectedIconPath

完整 theme.json 示例

json
{
  "light": {
    "navigationBarTextStyle": "black",
    "navigationBarBackgroundColor": "#efeff4",
    "backgroundColorContent": "#ffffff",
    "tabBarPagebackgroundColorContent": "#efeff4",
    "backgroundColor": "#f8f8f8",
    "backgroundTextStyle": "dark",

    "tabBarColor": "#7A7E83",
    "tabBarSelectedColor": "#007AFF",
    "tabBarBorderStyle": "black",
    "tabBarBackgroundColor": "#F8F8F8",

    "tabBarComponentIconPath": "static/tabbar/dark/ui.png",
    "tabBarComponentSelectedIconPath": "static/tabbar/dark/ui1.png",
    "tabBarAPIIconPath": "static/tabbar/dark/api.png",
    "tabBarAPISelectedIconPath": "static/tabbar/dark/api1.png",
    "tabBarCSSIconPath": "static/tabbar/dark/table.png",
    "tabBarCSSSelectedIconPath": "static/tabbar/dark/table1.png",
    "tabBarTemplateIconPath": "static/tabbar/dark/template.png",
    "tabBarTemplateSelectedIconPath": "static/tabbar/dark/template1.png",
    "tabBarMineIconPath": "static/tabbar/dark/my.png",
    "tabBarMineSelectedIconPath": "static/tabbar/dark/my1.png",

    "infoNormal": "#909399",
    "infoDark": "#82848a",
    "infoLight": "#f4f4f5",

    "primaryNormal": "#2979ff",
    "primaryDark": "#2b85e4",
    "primaryLight": "#dcedff",

    "successNormal": "#19be6b",
    "successDark": "#18b566",
    "successLight": "#DFEAE2",

    "warningNormal": "#ff9900",
    "warningDark": "#f29100",
    "warningLight": "#fff1dd",

    "errorNormal": "#fa3534",
    "errorDark": "#dd6161",
    "errorLight": "#ffe0e0",

    "infoNormalColor": "#ffffff",
    "infoDarkColor": "#ffffff",
    "infoLightColor": "#909399",
    "infoPlainColor": "#909399",

    "primaryNormalColor": "#ffffff",
    "primaryDarkColor": "#ffffff",
    "primaryLightColor": "#2979ff",
    "primaryPlainColor": "#2979ff",

    "successNormalColor": "#ffffff",
    "successDarkColor": "#ffffff",
    "successLightColor": "#19be6b",
    "successPlainColor": "#19be6b",

    "warningNormalColor": "#ffffff",
    "warningDarkColor": "#ffffff",
    "warningLightColor": "#ff9900",
    "warningPlainColor": "#ff9900",

    "errorNormalColor": "#ffffff",
    "errorDarkColor": "#ffffff",
    "errorLightColor": "#fa3534",
    "errorPlainColor": "#fa3534",

    "textPrimary": "#303133",
    "textRegular": "#606266",
    "textSecondary": "#909399",
    "textPlaceholder": "#C0C4CC",

    "radiusLarge": "20",
    "radiusMedium": "16",
    "radiusSmall": "12",
    "radiusMini": "10",

    "marginLarge": "24",
    "marginMedium": "20",
    "marginSmall": "16",
    "marginMini": "12",

    "borderBase": "#DCDFE6",
    "borderLight": "#E4E7ED",
    "borderLighter": "#EBEEF5",
    "borderExtraLight": "#F2F6FC",

    "paddingLarge": "24",
    "paddingMedium": "20",
    "paddingSmall": "16",
    "paddingMini": "12",

    "fontSizeLarge": "36",
    "fontSizeMedium": "28",
    "fontSizeSmall": "24",
    "fontSizeMini": "20",

    "sizeRatioLarge": "1.1",
    "sizeRatioMedium": "1",
    "sizeRatioSmall": "0.9",
    "sizeRatioMini": "0.8"
  },
  "dark": {
    "navigationBarTextStyle": "white",
    "navigationBarBackgroundColor": "#1F1F1F",
    "backgroundColorContent": "#646464",
    "tabBarPagebackgroundColorContent": "#1F1F1F",
    "backgroundColor": "#1F1F1F",
    "backgroundTextStyle": "light",

    "tabBarColor": "#cacaca",
    "tabBarSelectedColor": "#007AFF",
    "tabBarBorderStyle": "white",
    "tabBarBackgroundColor": "#1F1F1F",

    "tabBarComponentIconPath": "static/tabbar/dark/ui.png",
    "tabBarComponentSelectedIconPath": "static/tabbar/dark/ui1.png",
    "tabBarAPIIconPath": "static/tabbar/dark/api.png",
    "tabBarAPISelectedIconPath": "static/tabbar/dark/api1.png",
    "tabBarCSSIconPath": "static/tabbar/dark/table.png",
    "tabBarCSSSelectedIconPath": "static/tabbar/dark/table1.png",
    "tabBarTemplateIconPath": "static/tabbar/dark/template.png",
    "tabBarTemplateSelectedIconPath": "static/tabbar/dark/template1.png",
    "tabBarMineIconPath": "static/tabbar/dark/my.png",
    "tabBarMineSelectedIconPath": "static/tabbar/dark/my1.png",

    "infoNormal": "#909399",
    "infoDark": "#82848a",
    "infoLight": "#f4f4f5",

    "primaryNormal": "#2979ff",
    "primaryDark": "#2b85e4",
    "primaryLight": "#dcedff",

    "successNormal": "#19be6b",
    "successDark": "#18b566",
    "successLight": "#DFEAE2",

    "warningNormal": "#ff9900",
    "warningDark": "#f29100",
    "warningLight": "#fff1dd",

    "errorNormal": "#fa3534",
    "errorDark": "#dd6161",
    "errorLight": "#ffe0e0",

    "infoNormalColor": "#ffffff",
    "infoDarkColor": "#ffffff",
    "infoLightColor": "#909399",
    "infoPlainColor": "#909399",

    "primaryNormalColor": "#ffffff",
    "primaryDarkColor": "#ffffff",
    "primaryLightColor": "#2979ff",
    "primaryPlainColor": "#2979ff",

    "successNormalColor": "#ffffff",
    "successDarkColor": "#ffffff",
    "successLightColor": "#19be6b",
    "successPlainColor": "#19be6b",

    "warningNormalColor": "#ffffff",
    "warningDarkColor": "#ffffff",
    "warningLightColor": "#ff9900",
    "warningPlainColor": "#ff9900",

    "errorNormalColor": "#ffffff",
    "errorDarkColor": "#ffffff",
    "errorLightColor": "#fa3534",
    "errorPlainColor": "#fa3534",

    "textPrimary": "#E5EAF3",
    "textRegular": "#Cfd3dc",
    "textSecondary": "#A3A6AD",
    "textPlaceholder": "#8D9095",

    "radiusLarge": "20",
    "radiusMedium": "16",
    "radiusSmall": "12",
    "radiusMini": "10",

    "marginLarge": "24",
    "marginMedium": "20",
    "marginSmall": "16",
    "marginMini": "12",

    "borderBase": "#4C4D4F",
    "borderLight": "#414243",
    "borderLighter": "#363737",
    "borderExtraLight": "#2B2C2C",

    "paddingLarge": "24",
    "paddingMedium": "20",
    "paddingSmall": "16",
    "paddingMini": "12",

    "fontSizeLarge": "36",
    "fontSizeMedium": "28",
    "fontSizeSmall": "24",
    "fontSizeMini": "20",

    "sizeRatioLarge": "1.1",
    "sizeRatioMedium": "1",
    "sizeRatioSmall": "0.9",
    "sizeRatioMini": "0.8"
  }
}

配置完成后,调用相应 API,框架会自动设置属性,展示对应主题下的颜色。

在 hello uni-app x 中,已经配置了 theme.json,在 API 的主题切换示例中,可以体验。

注意:

  • iOS 13+、Android 10+ 设备上才支持暗黑模式
  • 把官方这个主题的文档写到我的主题文档里面就放在最前面

VaporCSS 主题配置表

新的主题配置采用双主题结构,包含 lightdark 两个主题模式。

说明:新版主题是在 UniApp X 官方主题的基础上进行扩展,完全适配官方主题配置。您可以在官方主题的基础上添加自定义的设计,实现更丰富的主题定制能力。 undColorContent; | 内容区域背景颜色 |

主题定制最佳实践

  1. 双主题结构:采用 lightdark 双主题结构,支持浅色和深色模式
  2. 集中管理:所有设计集中在 theme.json 中管理
  3. 命名规范:使用 PascalCase 命名规范,如 primaryNormalsuccessLight
  4. 层次结构:为每个颜色类型提供 normal、dark、light 三种状态,以及对应的文本颜色
  5. 一致性:保持间距、圆角、字体大小在两个主题中的一致性
  6. 扩展性:预留足够的扩展空间,便于后续主题迭代
  7. 导航栏配置:直接在主题配置中设置导航栏和 TabBar 的样式
  8. 图标路径:统一管理 TabBar 图标的路径,支持主题切换时的图标适配