# 配置小程序深色模式

在小程序的[全局配置项](https://open.feishu.cn/document/uYjL24iN/uEDNuEDNuEDN#c011c4d1)中，可通过 darkmode 属性配置小程序的深色模式（DarkMode）。本文介绍深色模式的配置流程，以及深色模式相关的配置说明。

## 版本要求

- 飞书自 v5.3.0 版本开始支持小程序深色模式。
- 飞书开发者工具自 v2.5.3 版本开始支持小程序深色模式。

## 步骤一：开启小程序深色模式

在小程序项目的根目录中打开 app.json 文件，在该文件中配置 `darkmode` 属性为 `true` 即表示当前小程序已开启深色模式。

开启后，小程序的基础组件会跟随系统主题展示不同的默认样式，但需要注意一部分自定义组件的默认样式可能存在异常（例如，深色模式下背景色和字体均为黑色）。因此，你需要继续进行下一步操作，配置深色模式的相关变量。

## 步骤二：配置深色模式相关变量

当你在项目根目录的 app.json 文件中配置了 `darkmode` 属性为 `true` 后，可以指定一个 theme.json 文件，通过该文件，以变量的形式定义不同主题下的 UI 颜色与图标。
**缺省样式说明**：

- 如果你在 app.json 文件中配置了 `darkmode` 属性为 `true`，但没有通过 app.json 和 theme.json 文件定义深色模式下的 UI 样式，则 UI 样式默认保持原有的浅色模式下的样式。

- 如果你调用小程序的 API （例如，[setNavigationBarColor](https://open.feishu.cn/document/uYjL24iN/ucjMyUjL3IjM14yNyITN)、[setTabBarStyle](https://open.feishu.cn/document/uYjL24iN/uITN04iM1QjLyUDN) 等）修改样式属性，则小程序框架将不再会响应原 DarkMode 配置中的样式（即通过 app.json 和 theme.json 文件定义的样式）。因此，你需要根据实际开发情况合理配置业务代码，避免因调用小程序 API 导致原 DarkMode 配置失效。通过配置文件定义主题样式与通过 API 修改主题样式的区别如下：

- 如果你通过 app.json 和 theme.json 文件定义 UI 样式，则小程序框架会按照 theme.json 文件的配置，自动调整不同主题下的 UI 样式。

- 小程序 API 不会在切换主题时自动适配，如果你需要通过小程序 API 修改不同主题的样式，则需要先[监听主题切换事件](https://open.feishu.cn/document/uYjL24iN/uQTM5UjL0ETO14CNxkTN/darkmode#1c4089e9)，在接收到指定的主题切换事件后，再去调用 API 修改样式以适配当前的主题。

1. 在 app.json 文件中配置 `themeLocation` 属性，属性值为变量配置文件 theme.json 相对于项目根目录的路径。

例如，你在项目根目录下新增变量配置文件 theme.json，需要配置的属性为`"themeLocation": "theme.json"`。

2. 在 theme.json 文件中定义变量。

支持定义的变量如下，各个变量的描述信息，可查阅[配置小程序](https://open.feishu.cn/document/uYjL24iN/uEDNuEDNuEDN)。

全局配置 window 属性与页面配置下的属性 | 全局配置 window.tabBar 下的属性
---|---
- navigationBarBackgroundColor<br>- navigationBarTextStyle<br>- backgroundColor<br>- backgroundTextStyle<br>- backgroundColorTop<br>- backgroundColorBottom | - color<br>- selectedColor<br>- backgroundColor<br>- borderStyle<br>- list<br>- iconPath<br>- selectedIconPath

theme.json 文件通过下表所示的属性定义变量。

属性 | 类型 | 是否必填 | 描述
---|---|---|---
light | object | 是 | 浅色模式下的变量定义。
dark | object | 是 | 深色模式下的变量定义。

其中的 `light` 和 `dark` 属性均以 `key: value` 的格式定义变量名和变量值，配置示例如下所示。

```json
{
  "light": {
    "navBgColor": "#f6f6f6",
    "navTxtStyle": "black"
  },
  "dark": {
    "navBgColor": "#191919",
    "navTxtStyle": "white"
  }
}
```

3. 在 theme.json 文件中完成变量的定义后，返回根目录的 app.json 文件中，在相应的全局配置或页面配置的相关属性中，通过`@`开头引用变量。

在 app.json 文件中引用变量的示例配置如下所示。由于在 theme.json 文件中分别定义了浅色模式（light）和深色模式（dark）的变量值，因此在此处配置完成后，小程序框架会自动根据系统主题，切换对应的小程序主题颜色。

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

// 页面配置

{
      "navigationBarBackgroundColor": "@navBgColor",
      "navigationBarTextStyle": "@navTxtStyle"
    }
    ```

### app.json 文件配置示例
以下配置示例中，仅提供主题颜色配置项，省略了其他配置项。

```json
{
    "window": {
        "navigationBarBackgroundColor": "@navBgColor",
        "navigationBarTextStyle": "@navTxtStyle",
        "backgroundColor": "@bgColor",
        "backgroundTextStyle": "@bgTxtStyle",
        "backgroundColorTop": "@bgColorTop",
        "backgroundColorBottom": "@bgColorBottom"
    },
    "tabBar": {
        "color": "@tabFontColor",
        "selectedColor": "@tabSelectedColor",
        "backgroundColor": "@tabBgColor",
        "borderStyle": "@tabBorderStyle",
        "list": [{
            "iconPath": "@iconPath1",
            "selectedIconPath": "@selectedIconPath1"
        }, {
            "iconPath": "@iconPath2",
            "selectedIconPath": "@selectedIconPath2"
        }]
    }
}
```

### theme.json 文件配置示例

```json
{
    "light": {
        "navBgColor": "#f6f6f6",
        "navTxtStyle": "black",
        "bgColor": "#ffffff",
        "bgTxtStyle": "light",
        "bgColorTop": "#eeeeee",
        "bgColorBottom": "#efefef",
        "tabFontColor": "#000000",
        "tabSelectedColor": "#3cc51f",
        "tabBgColor": "#ffffff",
        "tabBorderStyle": "black",
        "iconPath1": "image/icon1_light.png",
        "selectedIconPath1": "image/selected_icon1_light.png",
        "iconPath2": "image/icon2_light.png",
        "selectedIconPath2": "image/selected_icon2_light.png"
    },
    "dark": {
        "navBgColor": "#191919",
        "navTxtStyle": "white",
        "bgColor": "#1f1f1f",
        "bgTxtStyle": "dark",
        "bgColorTop": "#191919",
        "bgColorBottom": "#1f1f1f",
        "tabFontColor": "#ffffff",
        "tabSelectedColor": "#51a937",
        "tabBgColor": "#191919",
        "tabBorderStyle": "white",
        "iconPath1": "image/icon1_dark.png",
        "selectedIconPath1": "image/selected_icon1_dark.png",
        "iconPath2": "image/icon2_dark.png",
        "selectedIconPath2": "image/selected_icon2_dark.png"
    }
}
```

## 深色模式相关配置说明

### 获取当前系统主题

- 如果项目根目录的 app.json 文件中声明了 `"darkmode": true`，则 [tt.getSystemInfo](https://open.feishu.cn/document/uYjL24iN/uQjNx4CN2EjL0YTM) 或 [tt.getSystemInfoSync](https://open.feishu.cn/document/uYjL24iN/uUjNx4SN2EjL1YTM) 接口的返回结果中会包含 `theme` 属性，属性值为 `light` 或 `dark`。

- 如果项目根目录的 app.json 文件中未声明 `"darkmode": true`，则 tt.getSystemInfo 或 tt.getSystemInfoSync 接口无法获取到 `theme` 属性，此时属性值为 `undefined`。

### 监听主题切换事件

支持以下监听方式：

- 方式一：在项目代码的 `App()` 函数中传入 `onThemeChange` 回调方法，在小程序切换主题时会触发此回调方法。

- 方式二：通过 [tt.onThemeChange](https://open.feishu.cn/document/uYjL24iN/uUTOuUTOuUTO/darkmode/onthemechange) 接口监听主题切换。后续可通过 [tt.offThemeChange](https://open.feishu.cn/document/uYjL24iN/uUTOuUTOuUTO/darkmode/offthemechange) 接口取消监听。

### 适配 TTSS

TTSS 中，支持通过媒体查询 [prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) 适配不同主题，该方式与 Web 中适配方式一致。例如：

```css
/* 一般情况下的样式 start */
.some-background {
    background: white;
}
.some-text {
    color: black;
}
/* 一般情况下的样式 end */
@media (prefers-color-scheme: dark) {
    /* DarkMode 下的样式 start */
    .some-background {
        background: #1b1b1b;
    }
    .some-text {
        color: #ffffff;
    }
    /* DarkMode 下的样式 end */
}
```

### 飞书开发者工具的深色模式调试功能

在[飞书开发者工具](https://open.feishu.cn/document/uYjL24iN/ucDOzYjL3gzM24yN4MjN)内开发小程序过程中，可以开启深色模式调试开关，模拟该模式下小程序的样式与效果。

![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/1209f47d8ad84f6e70e29f3b5a0956b5_c7rgKOprni.png?height=732&lazyload=true&maxWidth=600&width=1776)