Communitygithub.com

bompus/hr-better-colors

Web UI 颜色规则:调色板渐变、语义化颜色令牌、颜色表示法与色域,以及渲染色对的测量对比度。适用于选择、审查或修复 Web UI 中的颜色、颜色令牌、主题或文本对比度。

hr-better-colors 是什么?

该技能为 Web UI 提供了一套严格的颜色系统规则,旨在解决常见的颜色错误——这些错误通常是系统性的,而非孤立的。它强调基于角色(role)命名颜色值,并通过测量实际渲染色对的对比度来确保可访问性,而非依赖人眼目测。技能支持 oklch() 等现代颜色表示法,并推荐从感知亮度、恒定色相、饱和度曲线等维度构建颜色渐变。它适用于所有支持颜色定义的 Web 界面系统,包括 React、Vue、Tailwind CSS 等框架和工具。该技能通过详细的检查清单和报告模板,帮助开发者在实际项目中系统性地审查和修复颜色问题,避免常见的陷阱如直接使用原始值、混用颜色符号、滥用语义令牌等。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/bompus/house-rules/tree/HEAD/skills/hr-better-colors

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

颜色

颜色系统是一小组渐变,按角色命名,并根据它们实际渲染的背景进行验证。大多数颜色错误都是系统性错误:一个孤立选取的值、一个因为看起来合适就借用的令牌、一对从未被测量过的色组。

永远不要报告一个你没有测量过的对比度值,也不要估计一个你可以计算出的颜色。颜色是界面中少数几个有精确答案的问题之一,所以请给出精确答案。

对比度要求属于 hr-better-accessibility。表面、阴影和图标颜色不在此技能范围内。

匹配项目的颜色系统

复用项目的令牌和表示法。为了修复一个值而添加的第二种表示法会使调色板更难理解。一个一致的十六进制系统胜过散布着 oklch() 的十六进制。

一旦令牌存在,就通过 lint 规则或守卫测试来强制执行,该测试会在令牌文件之外出现颜色字面量时失败,同时为那些需要原始值的地方设置一个简短的白名单。一条没有检查的“使用令牌”规则会随着时间的推移而偏离。

对于新系统,oklch() 是最好的默认选择,因为它的数值行为符合下面渐变规则所描述的规则。在其他情况下,一个颜色库会以项目自己的表示法产生相同的渐变(color-formats.md)。

系统是渐变,而不是颜色

一个中性渐变,一个强调渐变,以及产品实际渲染的状态渐变。一个没有被任何地方引用的 warning 渐变,是零像素的维护成本。只有当两样东西必须一眼就能区分开来时,第二个强调色相才有其地位。

每一步都有其职责

渐变不是一个可以通过目视挑选的渐变。每一步的存在是因为某个角色需要它:页面背景、组件悬停、边框、实心填充、正文文本。不要生成一个没有角色消耗的步骤。Tailwind 的 50–950 和 Radix 的 1–12 两种约定都可以映射到这些角色(palette-structure.md)。

按色相命名原始值,按角色命名语义值

原始值命名一个值(--blue-500),并且永远不直接应用于组件。语义令牌命名一个职责(--color-text-secondary),指向一个原始值,并且是组件引用的唯一层级。

这条分界线是使主题化成为可能的关键。没有它,深色模式意味着要审计每个用法,以确定哪个是“强调色”,哪个只是想要蓝色(token-naming.md)。

只在角色中使用令牌

永远不要因为一个令牌当前的值合适就借用它。一个用作文本颜色的分隔线,在边框变淡后就会跟着变淡。如果一个角色没有令牌,请添加令牌。

保持渐变中的色相恒定

一个结构良好的渐变由四个属性定义:

  • 步骤遵循一个有意的感知亮度渐进(palette-generation.md)。
  • 色相从头到尾保持恒定。
  • 鲜艳度在渐变的中间达到峰值,并在两端下降。
  • 步骤在亮端的分布比暗端更密集。

两端都止于纯黑和纯白之前,因为纯黑和纯白无法承载任何色相。使用颜色库而不是目视估算(palette-generation.md)。

一色一义

在整个界面中,一种颜色只用于一个目的,将色相相差 15° 范围内的任何颜色视为同一种颜色。如果强调色表示可交互,那么静态文本上的那种色相会告诉用户点击某些不可点击的东西,而一个看起来是中性的交互元素也同样具有误导性。颜色永远不是意义的唯一载体,这由 hr-better-accessibility 负责。

每个视图只填充一个操作

当填充色表示主要重点时,一个主要操作使用它,而同级的其他操作保持中性。将颜色放在背景上,而不是标签上。一个填充按钮从远处看就是主要的;而中性按钮上的强调色文本看起来像链接。

多个彩色背景是没问题的,只要它们表示不同的状态或类别,而不是作为同级的竞争元素。

测量实际渲染的色对,然后报告

测量一个前景色与它实际渲染的背景色之间的对比度,而不是页面背景色。当一对色组失败时,报告这对色组、它的测量值以及它缺失的阈值,然后保持颜色不变。它们是设计决策。只有在被要求时才更改它们,并在更改后重新测量(contrast.md)。

选择渐变的插值空间

插值空间是一种外观选择,而不是正确性设置。

  • in oklab 是最好的默认选择:亮度均匀,无色相意外。
  • in oklch 会绕着色相环移动,而不是穿过中间,从而保持鲜艳度,并在两个色相之间的所有过渡色上产生丰富的色彩。当两种色相的渐变在中间变灰时,可以使用它。
  • sRGB 默认值 会使中间点变暗和变灰。大多数已有的界面都是这种效果,因为这是你不指定任何选项时得到的结果。

参见 color-usage.md。

在完成之前

错误修复
项目中已有令牌,却使用了原始值复用或添加角色令牌,使用项目的表示法
在十六进制代码库中插入了一个孤立的 oklch() 值保持既定的表示法,除非正在进行迁移
在组件中直接使用像 --blue-500 这样的原始值用一个语义令牌指向它
令牌按其外观命名(--color-blue-button)或首次使用(--color-sidebar-gray)按其角色命名:--color-accent-solid、--color-bg-surface
--color-primary 表示品牌色,而 --color-text-primary 表示正文文本保留 accent 给品牌色;让 primary 表示“其组中最突出”的
语义令牌在其角色之外使用(如分隔线作为文本色)为缺失的角色添加令牌;永远不要按值借用
通过改变 HSL 亮度构建的渐变根据感知亮度重新构建,并保持色相恒定
在整个范围内均匀间隔的渐变收紧亮端,直到 50 和 100 呈现为两个不同的表面
不同色相使用相同的饱和度值匹配每种色相自身最大值的比例,而不是原始值
与强调色相冲突的状态色相移动它,直到破坏性操作和主要操作并排时能区分开来
通过机械地反转亮色调色板制作的深色模式反转作为起点,然后降低鲜艳度,加宽暗端,并重新检查每一对色组
prefers-color-scheme 设置一些令牌,而 .dark 类设置其他令牌选择一个切换机制并在整个项目中使用
通过改变色相来修复对比度改变亮度,这是对比度响应的通道
没有 sRGB 备选方案的 P3 颜色先声明 sRGB 值,然后在 @media (color-gamut: p3) 内部覆盖

报告

严重性。 HIGH 使内容无法阅读或分配了误导性的语义颜色。MEDIUM 是明显的主题、令牌或色域失败。LOW 是孤立的细节问题。

验证。 没有浏览器:令牌值、每个声明颜色的色域、存在两个主题块,以及从声明的令牌对计算出的对比度。有浏览器:文本实际渲染的背景,包括透明度及其下方的任何图像,在亮色和深色两种模式下测量。失败的色对被报告,而不是被重绘。报告你无法运行的每个检查为 未验证。

格式。 将发现结果按其违反的原则分组,按严重性排序,每个根因一行,列出其出现的每个位置:

严重性位置之前之后原因

位置 是 路径/到/文件:行。原因指出违反的原则和用户影响。

当有任何 HIGH 问题未解决时,报告 阻塞,否则报告 批准,并将剩余问题留在表中作为待办工作。永远不要对你没有检查的范围批准。如果没有任何可报告的,说明“没有可操作的颜色发现”并报告验证情况。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相关技能