AI配色方案生成与品牌一致性
原创
灵阙教研团队
B 基础 进阶 |
约 12 分钟阅读
更新于 2026-02-28 AI 导读
AI配色方案生成与品牌一致性 智能色板生成、和谐性算法与品牌规范的工程保障 1. 配色在产品设计中的地位 颜色是用户对产品的第一印象,也是品牌辨识度的核心载体。在 AI 产品中,配色还承担额外的语义职责:区分用户内容与 AI 生成内容、传达置信度、标识不同模型/功能区域。 配色的三个维度: +-------------------+ | 品牌维度 | <- 企业 CI 规范、品牌识别...
AI配色方案生成与品牌一致性
智能色板生成、和谐性算法与品牌规范的工程保障
1. 配色在产品设计中的地位
颜色是用户对产品的第一印象,也是品牌辨识度的核心载体。在 AI 产品中,配色还承担额外的语义职责:区分用户内容与 AI 生成内容、传达置信度、标识不同模型/功能区域。
配色的三个维度:
+-------------------+
| 品牌维度 | <- 企业 CI 规范、品牌识别
+-------------------+
| 功能维度 | <- 信息层级、状态指示、交互反馈
+-------------------+
| 情感维度 | <- 信任感、专业感、科技感
+-------------------+
1.1 AI 产品配色的特殊要求
| 需求 | 说明 | 约束 |
|---|---|---|
| 用户/AI 区分 | 用户消息与 AI 回复视觉可辨 | 色温/色相有明显差异 |
| 置信度色阶 | 高/中/低置信度需色彩编码 | 必须色盲安全 |
| 代码高亮 | 代码块需要语法高亮配色 | 深色背景高对比度 |
| 长时间阅读 | 用户长时间使用不疲劳 | 避免高饱和大面积色块 |
| 亮暗模式 | 同一色板适配两种模式 | 语义一致,视觉协调 |
2. 色彩理论基础
2.1 色彩空间
| 色彩空间 | 特点 | 适用场景 |
|---|---|---|
| RGB | 加色混合,设备直接使用 | 最终输出 |
| HSL | 色相/饱和度/亮度,直观 | 人工调色 |
| HSB/HSV | 类似 HSL,更贴合直觉 | 设计工具 |
| LCH | 感知均匀,人眼等距 | 算法生成 |
| OKLCH | 改进的 LCH,CSS 原生支持 | 现代 CSS |
| CIELAB | 感知均匀,色差计算 | 色差评估 |
2.2 和谐配色理论
色轮上的经典和谐关系:
互补色 (Complementary): 三色 (Triadic):
* *
/ \ / \
/ \ / \
*-----* *-----*
(180度对立) (120度间隔)
分裂互补 (Split-Complementary): 类似色 (Analogous):
* * * *
/ \ (相邻30度)
/ \
* --- *
(150+210度)
四色 (Tetradic): 正方 (Square):
*---* * *
| | | |
*---* * *
(两对互补) (90度间隔)
3. AI 配色生成算法
3.1 基于种子色的色板扩展
from colormath.color_objects import sRGBColor, LabColor
from colormath.color_conversions import convert_color
import colorsys
def generate_palette_from_seed(seed_hex: str, scheme: str = 'analogous') -> list:
"""从种子色生成和谐色板"""
r, g, b = hex_to_rgb(seed_hex)
h, s, l = colorsys.rgb_to_hls(r/255, g/255, b/255)
h_deg = h * 360
if scheme == 'analogous':
# 类似色: 种子 + 左右各 30 度
hues = [h_deg, (h_deg + 30) % 360, (h_deg - 30) % 360]
elif scheme == 'complementary':
# 互补色
hues = [h_deg, (h_deg + 180) % 360]
elif scheme == 'triadic':
# 三色
hues = [h_deg, (h_deg + 120) % 360, (h_deg + 240) % 360]
elif scheme == 'split_complementary':
# 分裂互补
hues = [h_deg, (h_deg + 150) % 360, (h_deg + 210) % 360]
palette = []
for hue in hues:
r2, g2, b2 = colorsys.hls_to_rgb(hue/360, l, s)
palette.append(rgb_to_hex(int(r2*255), int(g2*255), int(b2*255)))
return palette
def generate_shade_scale(base_hex: str, steps: int = 10) -> dict:
"""生成单色的明暗阶梯 (50-950)"""
r, g, b = hex_to_rgb(base_hex)
h, s, l = colorsys.rgb_to_hls(r/255, g/255, b/255)
# 明暗分布(模仿 Tailwind 的 50-950 阶梯)
lightness_map = {
50: 0.97, 100: 0.94, 200: 0.86, 300: 0.76,
400: 0.62, 500: 0.50, 600: 0.40, 700: 0.32,
800: 0.24, 900: 0.18, 950: 0.12,
}
scale = {}
for step, target_l in lightness_map.items():
# 在 OKLCH 空间中调整亮度更均匀
adjusted_s = s * (1 - abs(target_l - 0.5) * 0.4) # 极亮/极暗时降低饱和度
r2, g2, b2 = colorsys.hls_to_rgb(h, target_l, adjusted_s)
scale[step] = rgb_to_hex(
clamp(int(r2*255)),
clamp(int(g2*255)),
clamp(int(b2*255))
)
return scale
3.2 OKLCH 感知均匀配色
OKLCH 是目前最适合程序化生成配色的色彩空间,因为它在人眼感知上是均匀的。
// 使用 OKLCH 生成感知均匀的色板
// CSS Color Level 4 原生支持: oklch(L C H)
function generateOKLCHPalette(baseHue, scheme = 'analogous') {
const L = 0.65; // 亮度 (0-1)
const C = 0.15; // 彩度 (0-0.4)
let hues;
switch (scheme) {
case 'analogous':
hues = [baseHue, baseHue + 30, baseHue - 30];
break;
case 'complementary':
hues = [baseHue, baseHue + 180];
break;
case 'triadic':
hues = [baseHue, baseHue + 120, baseHue + 240];
break;
}
return hues.map(h => ({
css: `oklch(${L} ${C} ${h % 360})`,
hue: h % 360,
}));
}
// 在 CSS 中使用
// .primary { color: oklch(0.65 0.15 250); } /* 蓝色 */
// .accent { color: oklch(0.65 0.15 30); } /* 橙色 */
3.3 LLM 辅助配色
def generate_palette_with_llm(description: str) -> dict:
"""使用 LLM 生成语义化配色方案"""
prompt = f"""你是一位专业的 UI 配色设计师。根据以下描述生成一套产品配色方案。
描述: {description}
要求:
1. 输出 JSON 格式
2. 包含 primary, secondary, accent, success, warning, error 六组色
3. 每组色包含 main (主色) 和 contrast (对比色)
4. 所有文字/背景组合的对比度必须 >= 4.5:1
5. 配色必须色盲安全(红绿色盲可区分)
6. 适合长时间阅读,避免高饱和度
输出格式:
{{
"palette_name": "名称",
"mood": "情绪描述",
"primary": {{ "main": "#hex", "contrast": "#hex", "subtle": "#hex" }},
"secondary": {{ "main": "#hex", "contrast": "#hex", "subtle": "#hex" }},
"accent": {{ "main": "#hex", "contrast": "#hex" }},
"success": {{ "main": "#hex", "contrast": "#hex" }},
"warning": {{ "main": "#hex", "contrast": "#hex" }},
"error": {{ "main": "#hex", "contrast": "#hex" }},
"neutral": {{
"50": "#hex", "100": "#hex", "200": "#hex",
"300": "#hex", "400": "#hex", "500": "#hex",
"600": "#hex", "700": "#hex", "800": "#hex", "900": "#hex"
}}
}}"""
response = llm.generate(prompt)
palette = json.loads(response)
# 自动验证对比度
validate_contrast(palette)
# 自动验证色盲安全性
validate_color_blind_safety(palette)
return palette
4. 品牌一致性保障
4.1 品牌色彩规范
{
"brand": {
"name": "合规网",
"primary": {
"main": "#1E40AF",
"range": ["#1E3A8A", "#2563EB"],
"tolerance": 5
},
"secondary": {
"main": "#7C3AED",
"range": ["#6D28D9", "#8B5CF6"],
"tolerance": 5
},
"forbidden_colors": ["#FF0000", "#00FF00"],
"rules": {
"max_primary_area_percent": 30,
"min_neutral_area_percent": 40,
"primary_only_for": ["CTA_buttons", "links", "active_states"],
"logo_clear_space": "2x logo height",
"logo_min_contrast": 4.5
}
}
}
4.2 自动一致性检查
interface BrandComplianceResult {
score: number; // 0-100
issues: Issue[];
suggestions: string[];
}
function checkBrandCompliance(
pageColors: Color[],
brandConfig: BrandConfig
): BrandComplianceResult {
const issues: Issue[] = [];
// 1. 检查是否使用了品牌色
const usedPrimary = pageColors.some(c =>
colorDistance(c, brandConfig.primary.main) <= brandConfig.primary.tolerance
);
if (!usedPrimary) {
issues.push({
type: 'missing_brand_color',
severity: 'error',
message: '页面中未使用品牌主色'
});
}
// 2. 检查禁用色
for (const color of pageColors) {
for (const forbidden of brandConfig.forbidden_colors) {
if (colorDistance(color, forbidden) < 10) {
issues.push({
type: 'forbidden_color',
severity: 'error',
message: `使用了禁用颜色 ${color}(接近 ${forbidden})`
});
}
}
}
// 3. 检查色彩面积比例
const primaryArea = calculateColorArea(pageColors, brandConfig.primary.main);
if (primaryArea > brandConfig.rules.max_primary_area_percent) {
issues.push({
type: 'excessive_primary',
severity: 'warning',
message: `主色面积占比 ${primaryArea}%,超过上限 ${brandConfig.rules.max_primary_area_percent}%`
});
}
// 4. 检查对比度
for (const pair of getTextBackgroundPairs(pageColors)) {
const ratio = contrastRatio(pair.text, pair.bg);
if (ratio < 4.5) {
issues.push({
type: 'insufficient_contrast',
severity: 'error',
message: `对比度 ${ratio.toFixed(1)}:1 不足(要求 >= 4.5:1)`
});
}
}
const score = Math.max(0, 100 - issues.length * 15);
return { score, issues, suggestions: generateSuggestions(issues) };
}
4.3 色彩距离计算
// CIEDE2000 色差公式(最准确的感知色差)
function ciede2000(lab1, lab2) {
const [L1, a1, b1] = lab1;
const [L2, a2, b2] = lab2;
// 简化版 CIEDE2000
const dL = L2 - L1;
const Lbar = (L1 + L2) / 2;
const C1 = Math.sqrt(a1*a1 + b1*b1);
const C2 = Math.sqrt(a2*a2 + b2*b2);
const Cbar = (C1 + C2) / 2;
const dC = C2 - C1;
const dH = Math.sqrt(
Math.max(0, (a2-a1)**2 + (b2-b1)**2 - dC**2)
);
const SL = 1 + 0.015 * (Lbar - 50)**2 / Math.sqrt(20 + (Lbar - 50)**2);
const SC = 1 + 0.045 * Cbar;
const SH = 1 + 0.015 * Cbar;
return Math.sqrt(
(dL/SL)**2 + (dC/SC)**2 + (dH/SH)**2
);
}
// 色差阈值参考
// < 1: 人眼不可分辨
// 1-2: 近距离仔细看可分辨
// 2-5: 一眼可见差异
// 5-10: 明显不同的颜色
// > 10: 完全不同的颜色
5. 主题生成系统
5.1 从品牌色自动生成完整主题
function generateThemeFromBrand(primaryHex: string): Theme {
// 生成主色阶梯
const primaryScale = generateShadeScale(primaryHex);
// 自动选择互补色作为 accent
const [h, s, l] = hexToHSL(primaryHex);
const accentHue = (h + 180) % 360;
const accentHex = hslToHex(accentHue, s * 0.8, l);
const accentScale = generateShadeScale(accentHex);
// 生成中性色(带品牌色调的灰)
const neutralScale = generateNeutralScale(primaryHex);
// 组装亮色主题
const lightTheme = {
primary: primaryScale[600],
primaryHover: primaryScale[700],
primarySubtle: primaryScale[50],
accent: accentScale[500],
textPrimary: neutralScale[900],
textSecondary: neutralScale[600],
textMuted: neutralScale[400],
bgPrimary: '#FFFFFF',
bgSecondary: neutralScale[50],
border: neutralScale[200],
success: '#22C55E',
warning: '#F59E0B',
error: '#EF4444',
};
// 自动推导暗色主题
const darkTheme = deriveDarkTheme(lightTheme, primaryScale, neutralScale);
return { light: lightTheme, dark: darkTheme, scales: { primaryScale, accentScale, neutralScale } };
}
function generateNeutralScale(brandHex: string): Record<number, string> {
// 带品牌色调的中性灰色
const [h, s] = hexToHSL(brandHex);
const scale: Record<number, string> = {};
const lightnessMap = {
50: 97, 100: 94, 200: 86, 300: 75,
400: 56, 500: 45, 600: 35, 700: 25,
800: 15, 900: 8
};
for (const [step, lightness] of Object.entries(lightnessMap)) {
// 在中性灰中混入少量品牌色相
scale[Number(step)] = hslToHex(h, s * 0.05, lightness / 100);
}
return scale;
}
5.2 品牌色调的中性灰
纯灰: 品牌灰 (带蓝调):
#F9FAFB gray-50 #F8FAFC slate-50
#F3F4F6 gray-100 #F1F5F9 slate-100
#E5E7EB gray-200 #E2E8F0 slate-200
#D1D5DB gray-300 #CBD5E1 slate-300
#9CA3AF gray-400 #94A3B8 slate-400
#6B7280 gray-500 #64748B slate-500
#4B5563 gray-600 #475569 slate-600
#374151 gray-700 #334155 slate-700
#1F2937 gray-800 #1E293B slate-800
#111827 gray-900 #0F172A slate-900
品牌灰的优势:
- 与品牌色更和谐
- 更有"品牌感"
- 避免纯灰的"廉价感"
6. 色盲安全验证
6.1 验证流程
def validate_color_blind_safety(palette: dict) -> list:
"""验证色板的色盲安全性"""
critical_pairs = [
('success', 'error'), # 成功/错误必须可区分
('primary', 'accent'), # 主色/强调色必须可区分
('warning', 'error'), # 警告/错误必须可区分
]
issues = []
cb_types = ['protanopia', 'deuteranopia', 'tritanopia']
for type_name in cb_types:
for color_a_key, color_b_key in critical_pairs:
color_a = palette[color_a_key]['main']
color_b = palette[color_b_key]['main']
sim_a = simulate_color_blind(color_a, type_name)
sim_b = simulate_color_blind(color_b, type_name)
diff = ciede2000(hex_to_lab(sim_a), hex_to_lab(sim_b))
if diff < 15: # 色盲模拟后色差不足
issues.append({
'type': type_name,
'pair': (color_a_key, color_b_key),
'original_diff': ciede2000(
hex_to_lab(color_a), hex_to_lab(color_b)
),
'simulated_diff': diff,
'suggestion': f'{color_a_key} 和 {color_b_key} 在 {type_name} 色盲下难以区分'
})
return issues
6.2 安全色板模板
通用色盲安全色板 (经验证):
主要序列色:
蓝 #2563EB (安全: 色盲下仍为蓝)
橙 #F59E0B (安全: 色盲下仍为暖色)
紫 #7C3AED (安全: 色盲下偏蓝)
灰 #6B7280 (安全: 中性)
状态色:
成功 #2563EB + 对勾图标 (不用绿色! 用蓝色+图标)
错误 #EF4444 + 叉号图标 (红色 + 图标双重编码)
警告 #F59E0B + 感叹号 (橙色 + 图标)
替代方案:
用蓝/橙替代红/绿
用图标/形状/纹理辅助区分
用标签文字直接说明
7. 配色工具链
7.1 生成工具
| 工具 | 功能 | 输出 |
|---|---|---|
| Coolors.co | 随机配色生成 + 锁定调整 | HEX / RGB |
| Realtime Colors | 实时预览配色在界面上的效果 | CSS 变量 |
| Huemint | AI 配色生成 (品牌定制) | HEX |
| Leonardo (Adobe) | 基于对比度的配色生成 | Design Token |
| OKLCH Color Picker | OKLCH 空间手动调色 | oklch() |
| Tailwind CSS Colors | 预设色板参考 | Tailwind Config |
7.2 验证工具
| 工具 | 功能 |
|---|---|
| WebAIM Contrast Checker | 对比度计算 |
| Color Oracle | 色盲模拟(桌面应用) |
| Stark (Figma) | 对比度 + 色盲检查 |
| Chrome DevTools | 强制色彩模拟 |
| a11y.color | 批量对比度检查 |
8. CSS 现代配色技术
8.1 OKLCH 在 CSS 中的使用
:root {
/* OKLCH: 亮度 / 彩度 / 色相 */
--primary-l: 0.55;
--primary-c: 0.18;
--primary-h: 250;
--color-primary: oklch(
var(--primary-l)
var(--primary-c)
var(--primary-h)
);
/* 自动生成明暗变体 */
--color-primary-light: oklch(
calc(var(--primary-l) + 0.2)
calc(var(--primary-c) * 0.6)
var(--primary-h)
);
--color-primary-dark: oklch(
calc(var(--primary-l) - 0.15)
var(--primary-c)
var(--primary-h)
);
}
/* 暗色模式: 只调整亮度和彩度,色相不变 */
[data-theme="dark"] {
--primary-l: 0.72;
--primary-c: 0.14;
}
8.2 color-mix() 函数
:root {
--color-primary: #2563EB;
/* 自动生成透明度变体 */
--color-primary-10: color-mix(in oklch, var(--color-primary) 10%, transparent);
--color-primary-20: color-mix(in oklch, var(--color-primary) 20%, transparent);
--color-primary-50: color-mix(in oklch, var(--color-primary) 50%, transparent);
/* 与白色混合生成浅色变体 */
--color-primary-subtle: color-mix(in oklch, var(--color-primary) 15%, white);
/* 与黑色混合生成深色变体 */
--color-primary-dark: color-mix(in oklch, var(--color-primary) 80%, black);
}
9. 配色方案测试
9.1 自动化测试
// 配色方案自动化测试套件
describe('Color Palette Validation', () => {
const palette = loadPalette('brand-theme');
test('all text/background pairs meet WCAG AA contrast', () => {
const pairs = [
[palette.textPrimary, palette.bgPrimary],
[palette.textSecondary, palette.bgPrimary],
[palette.textPrimary, palette.bgSecondary],
[palette.primaryContrast, palette.primary],
];
for (const [fg, bg] of pairs) {
const ratio = contrastRatio(fg, bg);
expect(ratio).toBeGreaterThanOrEqual(4.5);
}
});
test('success and error colors are distinguishable under color blindness', () => {
const types = ['protanopia', 'deuteranopia'];
for (const type of types) {
const simSuccess = simulateColorBlind(palette.success, type);
const simError = simulateColorBlind(palette.error, type);
const diff = ciede2000(hexToLab(simSuccess), hexToLab(simError));
expect(diff).toBeGreaterThan(15);
}
});
test('primary color is within brand tolerance', () => {
const diff = ciede2000(
hexToLab(palette.primary),
hexToLab(brandConfig.primary.main)
);
expect(diff).toBeLessThan(brandConfig.primary.tolerance);
});
test('neutral scale has consistent hue shift', () => {
const hues = Object.values(palette.neutralScale).map(c => hexToHSL(c)[0]);
const hueVariance = standardDeviation(hues);
expect(hueVariance).toBeLessThan(5); // 色相偏差 < 5 度
});
});
9.2 视觉测试矩阵
| 测试维度 | 验证方法 | 通过标准 |
|---|---|---|
| 亮色模式 | 截图对比 | 无异常色块 |
| 暗色模式 | 截图对比 | 无异常色块 |
| 红绿色盲 | Color Oracle 模拟 | 所有状态可区分 |
| 蓝黄色盲 | Color Oracle 模拟 | 所有状态可区分 |
| 灰度模式 | 去色截图 | 层级仍可辨识 |
| 高对比度 | Windows 高对比度 | 界面可用 |
| 阳光下 | 降低对比度模拟 | 文字仍可读 |
10. 完整工作流
1. 品牌输入
品牌主色 + 品牌调性描述
|
v
2. 色板生成
AI 生成候选方案 (3 套)
+ 手动微调
|
v
3. 自动验证
对比度检查 + 色盲安全检查 + 品牌合规检查
|
v
4. 主题生成
从验证通过的色板自动生成:
- 亮色/暗色 Design Token
- Tailwind 配置
- CSS 自定义属性
|
v
5. 集成测试
在真实界面中预览
+ 视觉回归测试
+ 无障碍自动化测试
|
v
6. 发布与文档
Token 发布到设计系统
+ 使用指南文档
+ 品牌色彩使用规范
Maurice | maurice_wen@proton.me