为什么需要调色板生成器
设计师与前端工程师在日常工作中频繁面临色彩决策:品牌主色选什么?同一颜色的明暗阶梯怎么定?配色是否对色盲用户友好?文字在背景上的对比度是否达标?
传统流程是设计师在 Figma / Sketch 中手动调色,导出 HEX 后工程师再写入 CSS 变量或 Tailwind 配置。这个过程有几个痛点:
- 手动调色效率低:从主色生成 10 档色阶需要逐个调整明度与饱和度,难以保证档位间过渡均匀
- 可访问性检查易遗漏:WCAG 对比度需手动计算,色盲模拟需依赖设计软件插件
- 多平台导出繁琐:同一套色板要分别输出 CSS、Tailwind、SCSS、Android XML、iOS Swift 等格式
- 配色理论门槛高:互补色、类似色、分割互补等方案需要理解色环理论
在线调色板生成器正是为解决这些问题而生:输入一个主色,自动生成 6 种和谐方案、Tailwind/Material 色阶、明度色调阶梯,同时检查 WCAG 对比度与色盲可访问性,一键导出 6 种格式。
色彩理论基础:HSL 色环
调色板生成的数学基础是 HSL 色彩空间(Hue 色相、Saturation 饱和度、Lightness 亮度):
- 色相 H:0-360°,对应色环上的位置(0° 红、120° 绿、240° 蓝)
- 饱和度 S:0-100%,0% 灰色,100% 纯色
- 亮度 L:0-100%,0% 黑,100% 白,50% 纯色
相比 RGB 的三通道数值,HSL 更符合人眼对颜色的直觉感知:「这是什么颜色(H)→ 多鲜艳(S)→ 多亮(L)」。所有调色板算法都基于 HSL 的色相旋转与明度调整。
RGB 与 HSL 的转换是双向可逆的(见颜色格式转换工具),本工具内部统一以 RGB 为中介,需要色相操作时转 HSL,操作完成后再转回 RGB。
6 种和谐配色方案
和谐配色基于色环上色相的几何关系。本工具实现 6 种方案:
| 方案 | 色相旋转 | 色数 | 适用场景 |
|---|---|---|---|
| 互补色 | 0°, 180° | 2 | CTA 按钮强调(蓝底橙按钮) |
| 类似色 | -30°, 0°, 30° | 3 | 背景渐变、图表系列 |
| 三角色 | 0°, 120°, 240° | 3 | 品牌识别、三栏布局 |
| 分割互补 | 0°, 150°, 210° | 3 | 插画配色(对比但不刺眼) |
| 四角色 | 0°, 90°, 180°, 270° | 4 | 多主题、数据可视化 |
| 单色阶 | 同色相不同明度 | 5 | 企业站主色调(统一沉稳) |
算法实现核心是 generateHarmony(rgb, type):先转 HSL,按方案的 rotations 数组逐个旋转色相,保持饱和度与亮度不变。单色阶方案特殊处理:固定色相,生成 5 档明度(20/40/55/70/85)。
function generateHarmony(rgb: RGB, type: HarmonyType): RGB[] {
const hsl = rgbToHsl(rgb);
if (type === 'monochromatic') {
// 单色阶:同色相,明度 20/40/55/70/85 共 5 档
return [20, 40, 55, 70, 85].map((l) => hslToRgb({ h: hsl.h, s: hsl.s, l }));
}
return HARMONY_META[type].rotations.map((delta) =>
hslToRgb({ h: hsl.h + delta, s: hsl.s, l: hsl.l })
);
}
选型建议:先选 1 个主色 + 1 个强调色(互补或分割互补),再用类似色或灰色填充背景。避免同时使用 4 色以上强对比方案,会显得杂乱。
明度色调:Tints / Shades / Tones
同一颜色的明度变化是设计系统的核心。本工具实现三种色调阶梯:
- Tints(明色):向纯白渐变,明度提升 + 饱和度略降,适合背景与悬停态(hover)
- Shades(暗色):向纯黑渐变,明度降低,适合按下态(active)与边框
- Tones(浊色):向纯灰渐变,饱和度降低,适合次要元素与禁用态
算法核心是 generateTones(rgb, type, steps):根据 factor = (i + 1) / (steps + 1) 计算每档的渐变比例,tints 提升 l + (100 - l) * factor,shades 降低 l * (1 - factor),tones 降低 s * (1 - factor * 0.7)。
// Tints 算法:向纯白渐变
const l = hsl.l + (100 - hsl.l) * factor;
const s = hsl.s * (1 - factor * 0.3);
result.push(hslToRgb({ h: hsl.h, s, l }));
与设计系统色阶的区别:色阶覆盖从最亮到最暗的完整范围(50-950 共 11 档),色调阶梯只覆盖单一方向(仅亮 / 仅暗 / 仅浊)的 5 档。色调阶梯适合「我需要这个色的 hover 态」这类即时需求。
设计系统色阶:Tailwind 与 Material
主流设计系统都采用 10-11 档色阶,500 为主色,向亮暗两端递进。本工具实现 Tailwind(50-950 共 11 档)与 Material(50-900 共 10 档)两种规范。
生成算法
以输入色为 500 锚点,按经验公式向两端推导:
// 各档位相对 500 的明度偏移与饱和度系数
const adjustments = {
50: { lDelta: 42, sFactor: 0.7 }, // 最亮,明度+42,饱和度×0.7
100: { lDelta: 35, sFactor: 0.75 },
200: { lDelta: 27, sFactor: 0.82 },
300: { lDelta: 18, sFactor: 0.88 },
400: { lDelta: 8, sFactor: 0.95 },
500: { lDelta: 0, sFactor: 1 }, // 锚点,不变
600: { lDelta: -8, sFactor: 1.02 },
700: { lDelta: -16, sFactor: 1.05 },
800: { lDelta: -24, sFactor: 1.08 },
900: { lDelta: -32, sFactor: 1.1 },
950: { lDelta: -42, sFactor: 1.15 }, // 最暗,明度-42,饱和度×1.15
};
规律:向亮端明度提升 + 饱和度降低(避免亮色过于刺眼),向暗端明度降低 + 饱和度略提升(避免暗色发灰)。
与官方色板的差异
算法生成 ≠ 官方色板。Tailwind 与 Material 官方色板是设计师人工精调的结果,每个颜色的明度、饱和度、色相都经过仔细校准。算法生成的色阶接近官方风格但非完全等同,适合:
- 快速搭建原型(无需手动调色)
- 自定义品牌色生成完整色阶
- 学习色阶规律(理解明度与饱和度的变化趋势)
生产环境建议在算法生成基础上手动微调,或直接使用官方色板。
WCAG 2.1 对比度与无障碍设计
对比度计算
WCAG(Web Content Accessibility Guidelines)2.1 标准定义了文字与背景对比度的计算公式:
对比度 = (亮色相对亮度 + 0.05) / (暗色相对亮度 + 0.05)
相对亮度(relative luminance)的计算考虑了 sRGB 的 gamma 校正:
function relativeLuminance({ r, g, b }: RGB): number {
const channel = (n: number) => {
const c = n / 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
};
return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
}
对比度范围 1-21:1 表示无对比(同色),21 表示最大对比(黑白)。
合规等级
| 等级 | 普通文字 | 大字号(18pt 或 14pt 粗体) |
|---|---|---|
| AA | ≥ 4.5:1 | ≥ 3:1 |
| AAA | ≥ 7:1 | ≥ 4.5:1 |
本工具同时检查当前色与白字 / 黑字的对比度,标注合规等级。例如深蓝色背景白字通常通过 AA,浅黄色背景白字可能不达标需改用黑字。
实践建议
- 不要仅靠颜色传达信息:约 8% 男性存在色觉异常,若仅用红绿区分错误/成功,色盲用户无法识别。应同时用图标或文字标注
- 关键文字至少达到 AA:正文、按钮文字、表单标签必须 ≥ 4.5:1
- 大字号可放宽:标题、大图标文字 ≥ 3:1 即可
- 暗色模式重新检查:同一配色在亮色与暗色模式下对比度不同,需分别验证
色盲模拟:线性 RGB 矩阵变换
色盲类型
| 类型 | 患病率 | 影响 |
|---|---|---|
| 红色盲(Protanopia) | 约 1% 男性 | 红色感知缺失 |
| 绿色盲(Deuteranopia) | 约 1% 男性 | 绿色感知缺失(最常见) |
| 蓝色盲(Tritanopia) | 极罕见 | 蓝色感知缺失 |
矩阵变换原理
色盲模拟通过线性 RGB 变换矩阵实现。算法分三步:
- sRGB → 线性 RGB:反 gamma 校正(
c <= 0.04045 ? c/12.92 : ((c+0.055)/1.055)^2.4) - 矩阵乘法:3×3 矩阵变换,每种色盲一个矩阵
- 线性 RGB → sRGB:重新 gamma 校正
矩阵来源是 Machado et al. 2009 论文的简化版:
// 绿色盲变换矩阵(最常见)
const deuteranopia = [
0.367322, 0.860646, -0.227968,
0.280085, 0.672501, 0.047413,
-0.011820, 0.042940, 0.968881
];
// 矩阵乘法:new_r = m[0]*r + m[1]*g + m[2]*b
矩阵的物理含义:色盲患者缺少某种视锥细胞,大脑用其他细胞的响应「近似」缺失通道。矩阵的每一行描述了「新通道如何由原始三通道线性组合」。
为什么要做色盲模拟
约 8% 男性存在不同程度的色觉异常。若配色仅靠红绿区分(如红=错误、绿=成功),色盲用户无法识别。本工具展示当前色在色盲眼中的实际呈现,便于调整配色。建议:
- 同时用颜色 + 图标 / 文字标注状态
- 避免红色与绿色作为唯一区分手段
- 用本工具检查关键配色在三种色盲下的可区分性
多格式导出实践
本工具支持 6 种格式导出,覆盖主流前端与移动端开发场景:
CSS 变量
:root {
--primary-50: #eff6ff;
--primary-100: #dbeafe;
--primary-500: #2b6cff;
--primary-900: #1e3a8a;
}
用法:color: var(--primary-500);。适合原生 CSS 与 CSS-in-JS。
Tailwind 配置
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#2b6cff',
900: '#1e3a8a',
}
}
}
}
};
用法:className="bg-primary-500 text-primary-900"。Tailwind 4.0 后也支持 CSS 变量配置。
SCSS 变量
$primary-50: #eff6ff;
$primary-500: #2b6cff;
$primary-900: #1e3a8a;
用法:color: $primary-500;。适合传统 SCSS 项目。
JSON
{
"50": "#eff6ff",
"500": "#2b6cff",
"900": "#1e3a8a"
}
供 JavaScript 动态加载或设计工具导入。
Android XML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary_500">#2B6CFF</color>
</resources>
放入 res/values/colors.xml,用法:@color/primary_500。
iOS Swift
extension UIColor {
static var primary500: UIColor { UIColor(red: 0.169, green: 0.424, blue: 1.000, alpha: 1.0) }
}
用法:UIColor.primary500。
黄金角度随机配色
算法原理
随机配色采用黄金角度旋转采样(137.508°):从随机起始色相开始,每次旋转 137.508° 取下一个色相,保证色相在色环上分布最均匀。
function randomHarmony(count = 5): RGB[] {
const goldenAngle = 137.508;
const startH = Math.floor(Math.random() * 360);
const s = 60 + Math.floor(Math.random() * 30); // 60-90 饱和度
const l = 45 + Math.floor(Math.random() * 15); // 45-60 亮度
const result: RGB[] = [];
for (let i = 0; i < count; i++) {
const h = (startH + i * goldenAngle) % 360;
result.push(hslToRgb({ h, s, l }));
}
return result;
}
为什么是黄金角度
黄金角度(137.508°)是数学上最优的均匀分布角度,源自向日葵种子排列、松果鳞片等自然现象。其数学性质是:任何两个相邻采样的角度差都是黄金角度的整数倍,保证色相在色环上既不扎堆也不遗漏。
对比纯随机采样:纯随机可能产生色相扎堆(如 5 个色都集中在红色区域)或遗漏(如完全没有蓝色),黄金角度采样保证 5 个色均匀分布在 360° 色环上。
饱和度与明度固定在中等范围(S: 60-90, L: 45-60),保证生成的配色既鲜艳又不刺眼。
纯原生 TypeScript 实现要点
本工具的算法库 colorPalette.ts 约 460 行,零第三方依赖,全部基于浏览器原生 API:
- RGB ↔ HSL 互转:标准公式,clampByte/clampPercent/clampHue 三个工具函数处理边界
- 色相循环:
((n % 360) + 360) % 360保证负数也能正确映射到 0-360 - WCAG 相对亮度:注意 gamma 校正的两个分支(0.03928 阈值)
- 色盲矩阵:3×3 矩阵乘法,注意 sRGB ↔ 线性 RGB 的转换
- 导出格式:switch 分支处理 6 种格式,字符串模板拼接
避坑指南:
- Astro 模板中
{会被当作表达式开始,FAQ 中含字面量花括号需用{/}转义(详见 CSS 格式化工具博客) useMemo依赖数组要包含所有派生输入,避免缓存过期- 拾色器
input[type=color]的value必须是 6 位 HEX,3 位简写会报错
工具联动与实战流程
站点提供三个颜色相关工具,互补使用形成完整色彩工作流:
- 颜色格式转换工具:HEX / RGB / HSL / HSV / CMYK 五格式互转 + 简单和谐方案
- 调色板生成器(本工具):调色板生成 + 设计系统色阶 + 多格式导出
- 颜色对比度检查工具:双色对比度精确检查 + WCAG 合规判定
典型流程
- 在 /color 选基础色(拾色器或输入 HEX),获取 HSL 值了解色相
- 在 /color-palette 生成完整色阶与和谐方案,导出 CSS 变量或 Tailwind 配置
- 在 /color-contrast 验证关键组合(如主色背景 + 白字、强调按钮 + 主色背景)的对比度
- 用色盲模拟检查关键配色在三种色盲下的可区分性
局限性与改进方向
本工具仍有改进空间:
- 色阶生成非官方精调:算法生成接近但非完全等同 Tailwind/Material 官方色板,未来可引入 OKLCH 色彩空间提升感知均匀性
- 色盲模拟为简化版:使用 Machado 2009 简化矩阵,未模拟异常三色视觉(anomalous trichromacy,如红色弱)
- 未支持 OKLCH / LCH 色彩空间:CSS Color Level 4 引入的感知均匀色彩空间,色阶过渡更自然
- 未支持色彩主题切换:当前仅生成单一色板,未来可生成亮色 / 暗色双主题色板
- 未支持色彩提取:从图片提取主色调生成配色方案
小结
调色板生成器是色彩工作流的核心工具:从单一主色出发,自动生成完整设计系统色阶、和谐配色方案、明度色调阶梯,同时检查 WCAG 对比度与色盲可访问性,一键导出 6 种格式。配合颜色格式转换工具与对比度检查工具,覆盖了从选色、生成、验证到导出的完整流程。
理解色彩理论(HSL 色环、和谐方案、明度色调)、无障碍标准(WCAG 对比度、色盲模拟)、设计系统规范(Tailwind/Material 色阶)是做好配色的基础。希望本文与配套工具能帮助你更高效地完成色彩决策。