颜色调色板
将基础颜色扩展为感知均匀的渐变,并组合成调色板。所有数学运算委托给内置生成器;此技能的判断体现在配置和验证上。
原理(为何使用 OKLCH)
- 绝不在 HSL/RGB 中生成渐变。 HSL 亮度会误导(相同值并不意味着相同的感知亮度),并且在调色过程中色相会发生偏移。相等的 HSL 亮度会让黄色看起来太亮,蓝色看起来太暗。
- OKLCH 是工作空间:L(亮度)、C(色度)、H(色相)——相同的数值看起来相同,且是原生 CSS 支持的。
- 每步色度必须进行色域裁剪。 在非常亮/暗的步骤中,高色度在物理上是不可能的;生成器会降低色度,而不是让浏览器来裁剪。
- 一个对比度锚点:白色文本从 L ≈ 0.55 向下满足 WCAG AA,黑色文本从 L ≈ 0.60 向上满足。中间步骤放置在这些目标附近。
完整理论和来源:references/theory.md
工作流程
1. 明确目标
与用户确认(跳过已经知道的部分):基础颜色或品牌颜色;步数(11 为标准,9 较精简,12 适用于 Radix 风格的角色);调色板需要的色调(品牌色 + 语义色:成功/警告/危险/信息 + 中性色);是否需要暗模式?
2. 生成渐变
cd "{skill_dir}/scripts" && python3 generate_ramp.py "#3b82f6" --steps 11 --chroma 90
# 多色调调色板:一次调用,逗号分隔名称
python3 generate_ramp.py "#3b82f6" "#e11d48" "#22c55e" --names blue,red,green --format css
关键标志:--chroma N(每步色域最大值的百分比;通常 80-95,更高 = 更鲜艳),--hue-drift D(从亮到暗的故意色相偏移,例如深黄色趋向橙色;仅在要求时使用),--cvd(近视模拟的十六进制色),--format table|css|json。
多色调规则:在一次调用中生成所有色调,以便它们在每一步共享相同的亮度和色度百分比——这就是让 blue-500 和 red-500 感觉像兄弟的原因。切勿使用不同的边界重新生成一个色调。
3. 验证
阅读表格输出并检查:
- 亮度单调递增,相邻步级的 ΔE 大致恒定(均匀性列)
- 预期的前景/背景步级对满足 WCAG AA(白色文本需要步级中
vs-white ≥ 4.5;黑色文本vs-black ≥ 4.5) - 无跨色调 ΔE 警告(相同步级色调之间的 Oklab ΔE ≥ 0.05)
- 使用
--cvd:在用于承载意义的 UI 步级中,近视模拟的步级颜色仍然可区分
如果用户提供现有调色板进行审核,将每一步转换为 OKLCH(在重建上使用 --format json,或手动转换)并检查相同的四个要点。
4. 组合调色板
- 为步级分配角色(Radix 惯例):1-2 应用程序背景 · 3-5 组件背景(正常/悬停/活动) · 6-8 边框/焦点 · 9-10 纯色背景和悬停(步级 9 = 最纯,色度最高) · 11-12 文本(低/高对比度)。
- 语义别名:当色阶服务于一个含义时,使用
--danger-500,而不是--red-500。一个色阶可以支持多个别名。 - 暗模式 = 重新映射,不重新生成:保持色阶不变,翻转语义分配(最亮的步级变成最暗的表面,文本颜色两端交换)。OKLCH 中的感知均匀性使反向映射同样可读。
5. 交付
将 --format css 输出写入文件(@supports 内的自定义属性包含十六进制回退),并在聊天中附上验证报告。如果最终目标是设计系统,建议令牌命名(原始色阶 + 语义别名层级)。
常见修复
| 症状 | 修复 |
|---|---|
| 第 50/100 步看起来褪色 | 这是预期的——白色附近的色度在物理上受限;不要通过裁剪来“修复”它 |
| 色调的鲜艳度看起来不相等 | 所有色调使用同一次调用;尝试 --chroma 80 |
| 500 步级对白色文本的对比度测试失败 | 接受用于大文本/图形,或降低中间亮度(--hue-drift 没有帮助;移动锚点) |
| 深黄色看起来像橄榄色 | 有意识地使用 --hue-drift 10-15 趋向橙色,或接受作为品牌品味 |