首页
/ Material UI 颜色体系实战:从 Material Design 调色板到 createTheme 的调色方案

Material UI 颜色体系实战:从 Material Design 调色板到 createTheme 的调色方案

2026-09-06 20:45:06作者:尤辰城Agatha

本文以 Material UI(MUI)官方文档 Color 页面 为主体,系统讲解如何用 Material Design 颜色体系为你的 React 应用设计品牌色主题。读完后你将掌握:@mui/material/colors 调色板的结构(Hue/Shade)与引用方式、createTheme()palette 配置的完整写法、createTheme() 如何自动推导 light/dark/contrastText 的底层机制(对应源码 createPalette.js),以及如何对照 WCAG 2.2 调整对比度阈值。

1. Material Design 颜色系统概述

Material UI 开箱即用地实现了 Google Material Design 指南中的全部颜色。你可以基于 Material Design 颜色体系构建一个反映品牌或产品风格的色彩主题。核心概念只有两个:

  • Palette(调色板):一组由色相(hue)及其深浅(shade)组成的颜色集合。Material UI 提供了 Material Design 指南中的全部颜色,且这些颜色在设计上彼此协调。
  • Hue & Shade(色相与深浅):调色板中的单个颜色由一个色相(如 "red")和一个深浅(如 "500")共同标识。"red 50" 是最浅的红(偏粉色),"red 900" 是最深的红。此外,大多数色相还带有一组以 A 为前缀的 "accent" 深浅(A100/A200/A400/A700)。

2. 引用 2014 版 Material Design 调色板

这套调色板最初由 Material Design 于 2014 年创建,由一组设计上和谐共处的颜色组成,可直接用于开发品牌调色板。若要生成自己的一套和谐调色板,可使用第 3 节的调色板生成工具。

给定一个色相(HUE,如 red、pink)和一个深浅(SHADE,如 500、600),可以这样导入颜色:

import { red } from '@mui/material/colors';

const color = red[500];

仓库中该调色板的实现位于 packages/mui-material/src/colors/ 目录。以 red.js 为例,每个颜色文件导出一个以深浅为键、以 HEX 值为值的对象:

const red = {
  50: '#ffebee',
  100: '#ffcdd2',
  200: '#ef9a9a',
  300: '#e57373',
  400: '#ef5350',
  500: '#f44336',
  600: '#e53935',
  700: '#d32f2f',
  800: '#c62828',
  900: '#b71c1c',
  A100: '#ff8a80',
  A200: '#ff5252',
  A400: '#ff1744',
  A700: '#d50000',
};

调色板全貌

index.js 的导出可以看到,MUI 共内置 20 个色相调色板:

色相(camelCase 导出名) 说明 色相(camelCase 导出名) 说明
red / pink 红 / 粉 green / lightGreen 绿 / 浅绿
purple / deepPurple 紫 / 深紫 lime / yellow 青柠 / 黄
indigo / blue 靛蓝 / 蓝 amber / orange 琥珀 / 橙
lightBlue / cyan 浅蓝 / 青 deepOrange / brown 深橙 / 棕
teal 蓝绿 grey / blueGrey 灰 / 蓝灰

另外还有一个 common.js,仅含两个基础色:black: '#000'white: '#fff'

每个色相的深浅结构在官方示例 Color.js 中体现得很清楚:主深浅序列为 50, 100, 200, 300, 400, 500, 600, 700, 800, 900,accent 序列为 A100, A200, A400, A700

引用示例

例如,引用互补的主色 "red 500" 和强调色 "purple A200":

import { purple, red } from '@mui/material/colors';

const primary = red[500];        // #f44336
const accent = purple['A200'];   // #e040fb
const accent = purple.A200;      // #e040fb(等价写法)

3. 挑选颜色(Picking colors)

3.1 官方调色工具

Material Design 团队提供了一个官方的调色板配置工具:material.io/resources/color/。它可以帮助你为 UI 创建调色板,并测量任意颜色组合的无障碍等级。工具的输出可以直接填入 createTheme() 函数:

import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    primary: {
      light: '#757ce8',
      main: '#3f50b5',
      dark: '#002884',
      contrastText: '#fff',
    },
    secondary: {
      light: '#ff7961',
      main: '#f44336',
      dark: '#ba000d',
      contrastText: '#000',
    },
  },
});

3.2 文档内 Playground

Material UI 文档内置了一个交互 Playground(实现见 ColorTool.js),可以在文档站点上直接测试颜色方案:

  • 通过色相单选按钮(hues:red、pink、purple、deepPurple、indigo、blue、lightBlue、cyan、teal、green、lightGreen、lime、yellow、amber、orange、deepOrange)与深浅滑块(50~900 及 A100~A700)选择颜色;
  • 也可以直接在 Primary / Secondary 输入框中输入 HEX 或 rgb() 值,输入框会做正则校验(isRgb / isHex),仅合法颜色才会应用到主题。

Playground 生成的 palette 输出可以直接粘贴到 createTheme() 函数(配合 ThemeProvider 使用):

import { createTheme } from '@mui/material/styles';
import { purple } from '@mui/material/colors';

const theme = createTheme({
  palette: {
    primary: {
      main: purple[500],
    },
    secondary: {
      main: '#f44336',
    },
  },
});

只需要提供 main 深浅(除非你想进一步定制 lightdarkcontrastText),其余颜色由 createTheme() 自动计算。如果你直接传入 Material 调色板对象(如 primary: purple),createTheme() 会从该调色板中选取对应的默认深浅填充 main、light、dark——这一点由源码中的 augmentColor 逻辑保证,见下文第 5 节。

3.3 社区工具

官方文档还推荐了这些社区调色工具,用于快速生成、预览和编辑 MUI 主题:

  • mui-theme-creator:帮助设计与定制 Material UI 主题的工具,内置多种站点模板,展示各组件受主题影响的效果;
  • MUI Theme Builder:生成、预览、编辑 Material UI 主题的工具;
  • Material palette generator:即官方调色板生成器,可为任意输入颜色生成一套调色板;
  • MUI Theme Customizer:让实验和生成 Material UI 主题更加便捷的工具。

4. 底层原理:createTheme 如何"增强"你的颜色

文档说"只需提供 main",其依据在 createPalette.jsaugmentColor 函数中。它的工作流程如下:

  1. 补全 main:若你只传了 primary: red(即传入了完整调色板对象),augmentColor({ color, mainShade = 500, ... }) 会取 color[500] 作为 main;secondary 则默认取 A400(light 取 A200、dark 取 A700);
  2. 校验:颜色对象必须含有 main500 属性,且 color.main 必须是字符串,否则会抛出带修复建议的错误(错误信息中直接给出了 primary: greenprimary: { main: green[500] } 两种正确写法);
  3. 推导 light/dark:由 addLightOrDark 调用 colorManipulatorlighten/darken,按 tonalOffset(默认 0.2,dark 方向乘以 1.5)把 main 的亮度上移/下移约两档;
  4. 推导 contrastText:由 getContrastText(color.main) 完成,即在黑(rgba(0,0,0,0.87))与白(#fff)之间选择对比度更高的一方,达到 contrastThreshold(默认 3)。

默认调色板的取值也在同一文件中定义:light 模式下 primary 为 blue 700/400/800,secondary 为 purple 500/300/700,error 为 red 700/400/800,warninginfosuccess 分别基于 orange、lightBlue、green 调色板;dark 模式则整体改用更亮的深浅(如 primary 取 blue 200/50/400)。若你什么都不配置,主题就是这套默认值。

Playground 中"色条预览"展示的三个方块(dark/main/light)正是调用 theme.palette.augmentColor({ color: { main } }) 得到的结果(见 ColorTool.jscolorBar 函数),这与 createTheme() 内部走的完全是同一条代码路径。

5. 无障碍对比度(Accessibility)

WCAG 2.2 Success Criterion 1.4.3 建议文本与图片文本的视觉呈现至少保持 4.5:1 的对比度。Material UI 当前仅强制 3:1 的对比度。从源码看,这一阈值就是 createPalette 中的 contrastThreshold = 3 默认参数:getContrastText 用它判断黑白二选一,且在非 production 环境下,若最终对比度仍低于 3:1,会向控制台打印警告(指明 WCAG 2008 版对比度条款)。

若希望达到 WCAG 2.2 Level AA 合规,可以在 createThemepalette 中调高最小对比度阈值,具体方法见官方 Theme customization(palette) 页面的 Accessibility 小节:

import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    contrastThreshold: 4.5, // 提高至 WCAG 2.2 AA 建议值
  },
});

6. 小结

  • import { red } from '@mui/material/colors' + red[500] 的"Hue + Shade"方式从 2014 版 Material 调色板中取色,共 20 个色相、每色相 10 档主深浅 + 4 档 A 深浅;
  • 主题配置只需给 palette.primary/secondarymaincreateTheme() 会经 augmentColor 自动推导 lightdarkcontrastText(推导逻辑见 createPalette.js);
  • 选色可用 Material Design 官方调色工具、MUI 文档内 Playground 及多个社区主题工具;
  • 需要 WCAG 2.2 AA 对比度时,调高 palette.contrastThreshold(MUI 默认为 3:1)。
登录后查看全文
热门项目推荐
相关项目推荐