颜色选择器

点拾色器或输入十六进制色值,立刻得到 sRGB 与线性 RGB、相对亮度、HSL、与黑与白的对比度,以及这个底色上该用黑字还是白字。

规范化 HEX#FF0000
RGB 8 位rgb(255, 0, 0)
线性 RGB1.0000, 0.0000, 0.0000
相对亮度 L0.2126
与黑 #0000005.25:1
与白 #FFFFFF4.00:1
建议正文字色#000000(5.25:1)
HSL(取整)hsl(0, 100%, 50%)
HSL 往返 HEX#FF0000(一致)
示例文字:#FF0000 底色上建议用 #000000 作正文字色,对比度 5.25:1。
直接在 sRGB 上混 50%(与白色)#FF8080 · L=0.3811
先做 gamma 反变换再混 50%(与白色)#FFBCBC · L=0.6063

提示:在 HEX 框或三个通道框里按 Enter 可立即重新计算;打开页面时示例色是 #FF0000,与下面「完整示例」和对照表用的是同一个值。

使用方法

  1. 页面打开时已经是示例色 #FF0000(纯红),拾色器、HEX 框、R / G / B 三个框、结果卡和下面的「完整示例」用的是同一个值,可以直接对照。
  2. 换色有三种方式:拖拾色器、在 HEX 框输入 #RRGGBB(如 #315FE8)或三位缩写 #RGB(如 #F0A)、或在 R / G / B 三个框里各填 0~255 的整数。三处任意一处改动,其余两处自动同步。
  3. 看结果卡:相对亮度 L 是 WCAG 用来算对比度的中间量,线性 RGB 是 sRGB 做 gamma 反变换后的值,与黑 / 与白 两行给出这个颜色与纯黑、纯白的对比度。
  4. 看建议正文字色:工具取「与黑」「与白」中对比度较大的那个作正文色。示例色 #FF0000 建议 #000000,5.25:1,下面的预览块会按它真实渲染一段文字。
  5. 最下方的「混色演示」把当前色与白色各取一半,分别用「直接在 sRGB 上混」和「先线性化再混」算一遍,用来直观看出 gamma 的影响;点「复制全部色值」可把 9 张卡一次性带走。

这个颜色选择器能解决什么问题

一是判断文字压在底色上能不能看清。设计稿定了主色,正文用黑字还是白字凭眼睛看经常出错:中灰就是典型,#767676 上黑字 4.62:1、白字 4.54:1,都刚过 AA 线;再深一级的 #777777 上白字掉到 4.48:1 就不合格。本页把两个数字并排列出并给出建议值。

二是把三位缩写正确展开。从设计稿或旧代码里抄来的 #F0A、#ABC 这类缩写,展开规则是把每一位复制成两位:#F0A 是 #FF00AA,不是 #F0A000。规则写反了颜色会整体跑偏,本页输入缩写后会直接显示展开结果并给出提示。

三是解释「手动调浅以后颜色发灰」。把颜色和白色各取一半,结果比预期暗且发灰,原因是直接用 sRGB 编码值做算术、跳过了线性化。原理一节给出的实测差异是 #808000 与 #BCBC00,相对亮度差一倍以上。

四是快速核对无障碍阈值:某个色值对是否达到 4.5:1(正文)、3:1(大字与非文本)、7:1(AAA 正文)。本页把这三档判定直接写在结果里,完整的阈值对照表放在下面一节。

本页不做这些事:不检测成对的两种颜色(需要分别输入前景与背景并出具合规报告)——那请用颜色对比度检测;不打印 CMYK、不做印刷色转换——那是十六进制转RGB之外的专门页面负责;不生成互补色、邻近色等配色方案——请用互补色颜色查询;也不从图片里吸色,那是图片颜色取色。

sRGB、线性 RGB 与相对亮度:为什么必须先做 gamma 反变换

这个颜色选择器内部做的第一件事不是取颜色,而是把十六进制值拆成三个 0~255 的整数,并认定它们属于 sRGB 编码空间。日常写在 CSS 里的 #FF0000 就是 sRGB 编码值,它按 IEC 61966-2-1 定义的分段函数缩放:归一化通道值 c 不大于 0.04045 时,线性值是 c / 12.92;超过 0.04045 时,线性值是 ((c + 0.055) / 1.055) 的 2.4 次方。反过来的函数阈值是 0.0031308,小于等于它时乘以 12.92,大于它时用 1.055 乘 c 的 1 / 2.4 次方再减 0.055。

为什么不能跳过这一步。因为 sRGB 编码值不是线性的「光强比例」,而是做过非线性压缩的编码。把 #FF0000 与 #00FF00 各取一半:直接在编码值上平均得到 #808000,相对亮度 0.1986;先线性化、再平均、再编码回 sRGB 得到 #BCBC00,相对亮度 0.4639,差了 1.34 倍,肉眼就是「灰暗」与「明亮」的差别。单通道更极端:sRGB 的 0.5(128/255)对应线性值只有 0.2140,而线性空间的 0.5 编码回 sRGB 是 0.7354(188/255)——这正是分段函数中段最陡的原因。混色、渐变与亮度计算都必须先做 gamma 反变换。

相对亮度怎么算。WCAG 2.1 的公式是 L = 0.2126R + 0.7152G + 0.0722B,R、G、B 必须已经线性化并归一化到 0~1。三个系数来自 Rec.709 亮度权重,反映人眼对绿最敏感、对蓝最迟钝:纯绿 #00FF00 的 L 正好是 0.7152,纯红 0.2126,纯蓝 0.0722,纯黑 0,纯白 1。旧代码常见的 0.299 / 0.587 / 0.114 是 Rec.601 系数,套进 WCAG 口径是错的。

对比度怎么算。两个颜色的相对亮度记为 L1、L2,取较亮的作分子、较暗的作分母,对比度是 (L1 + 0.05) / (L2 + 0.05)。这个 + 0.05 是规范固定写死的偏移量,用来模拟屏幕表面的环境光反射,并避免纯黑背景时除零。黑白代进去就是 (1 + 0.05) / (0 + 0.05) = 21,所以 WCAG 对比度的量程是 1:1 到 21:1,超过 21 一定是公式写错了。

AA / AAA 的适用场景不一样。AA 的正文字号门槛是 4.5:1,大号文字只要 3:1;大号的定义是 18pt(约 24px)以上,或 14pt(约 18.66px)以上且加粗。AAA 更严:正文要 7:1,大号也要 4.5:1。另有 AA 的 1.4.11 要求非文本元素(图标、边框、开关、图表色块)与相邻颜色的对比度不低于 3:1。同一个 #FF0000,与白底 4.00:1,做正文不合格、做 24px 标题合格;与黑底 5.25:1,做正文合格。

HSL 与 sRGB 的转换不是无损几何关系。色相 H 是 0~360 的角度,每 60 度一段落在六个扇区;饱和度 S 与亮度 L 是百分比。用整数度的 H、整数百分比的 S / L 表示再转回 RGB,会因为四舍五入丢信息。实测把 #315FE8 转成 hsl(225, 80%, 55%) 再转回来得到 #305EE8,蓝通道差 1 级;256 个灰度逐一走一遍「HEX 到 HSL 取整再回 HEX」,有 155 个对不上,最大偏差 1 级。所以 HSL 适合调参,不适合当存储格式。

完整示例(数值仅作演示)

这个颜色选择器的示例条件与页面打开时的默认值完全一致:色值 #FF0000,即 RGB(255, 0, 0)。把它代进上面三条公式,逐步算一遍:

需要强调:这几个数字都是拿 8 位整数通道算出来的固定值,不依赖屏幕、系统或浏览器。你在自己的页面上把 #FF0000 填进去,得到的会是同一组数。

色值、相对亮度与对比度对照表

下表所有数字都由上面的公式逐项算出,保留两位小数。看这张表能快速建立直觉:同样是「纯色」,绿底黑字有 15.30:1,蓝底黑字只有 2.44:1——因为绿的亮度权重是蓝的将近 10 倍。

色值相对亮度 L与黑 #000000与白 #FFFFFF正文字色建议
#000000 纯黑0.00001.00:121.00:1白字(21.00:1)
#FFFFFF 纯白1.000021.00:11.00:1黑字(21.00:1)
#FF0000 纯红(默认)0.21265.25:14.00:1黑字(5.25:1)
#00FF00 纯绿0.715215.30:11.37:1黑字(15.30:1)
#0000FF 纯蓝0.07222.44:18.59:1白字(8.59:1)
#315FE8 品牌蓝0.14663.93:15.34:1白字(5.34:1)
#767676 中灰(压线通过)0.18124.62:14.54:1黑字(4.62:1)
#777777 中灰(压线不通过)0.18454.69:14.48:1黑字(4.69:1)
#808080 中灰0.21595.32:13.95:1黑字(5.32:1)

下面这张表把 AA / AAA 的字号门槛和适用场景列在一起,判定结果就是结果卡里显示的那一档:

条目正文(小于 24px)大字(≥ 24px 或 ≥ 18.66px 粗体)非文本(图标 / 边框 / 控件)
AA(1.4.3 与 1.4.11)4.5:13:13:1
AAA(1.4.6)7:14.5:1不适用

三位缩写的展开规则单独列一张表。关键点是把每一位复制成两位,而不是在右边补零:

三位缩写正确展开(复制半字节)错误写法(整体右补零)
#F0A#FF00AA#F0A000
#ABC#AABBCC#ABC000
#123#112233#123000
#F00#FF0000#F00000
#FFF#FFFFFF#FFF000

输入范围、边界与精度说明

常见问题

为什么红字白底只有 4.00:1?红不是很「跳」吗?

红看起来醒目,靠的是色相差异而不是亮度差异。#FF0000 的相对亮度只有 0.2126,白底是 1,代入公式得到 4.00,差 0.5 落到 AA 正文线之下。要当正文用就把红调深(例如 #CC0000 附近),或者只把它用在 24px 以上的标题——大字门槛 3:1,4.00 够用。

我直接用 (R + G + B) / 3 当亮度不行吗?

不行,两处都错。权重不该等分(绿 0.7152、红 0.2126、蓝 0.0722),而且必须先做 gamma 反变换。实测 #0000FF 的朴素均值是 0.3333,WCAG 相对亮度只有 0.0722,差 4.6 倍——按均值判断会把蓝底黑字误判成合格。旧代码里的 0.299 / 0.587 / 0.114 是 Rec.601 系数,与 WCAG 用的 Rec.709 不是一套。

#F0A 展开成 #FF00AA,为什么不是 #F0A000?

三位缩写的语义是「每一位代表一个通道」,不是「省略了后三位」。#F0A 的 F 是红、0 是绿、A 是蓝,各复制成两位得到 #FF00AA;右补零变成 #F0A000,红通道 F0、绿通道 A0,颜色从品红跑成暗黄绿。

为什么 #FF0000 的 HSL 转回来是原值,别的颜色就不是?

因为纯色(L 恒为 50%、S 恒为 100%)与灰阶(S 恒为 0%)恰好能对上原整数。S 或 L 一旦落在中间档,整数百分比就表示不了原通道值,回程出现 1 级误差。实测 7 个常见色里只有 #FF0000 完全一致;256 个灰度里有 155 个对不上。

黑白的对比度为什么正好是 21?

代入公式即得:黑 L = 0、白 L = 1,(1 + 0.05) / (0 + 0.05) = 21。相对亮度的取值是闭区间 [0, 1],所以任何一对颜色的对比度都落在 1:1 到 21:1 之间。看到超过 21 的数字,基本可以确定是公式写错了。

为什么有时候黑字白字都不达标?

看「与黑」「与白」两行:都不到 4.5 就说明底色落在中亮度陷阱里,典型是 #7F7F7F 一类中灰。正确做法不是硬凑文字色,而是把底色朝黑或朝白挪一点,让其中一个方向回到 7:1 以上。

为什么这里的对比度和设计软件里显示的不一样?

先确认口径。常见分叉有三个:用了 Rec.601 的系数而不是 Rec.709;忘了对 sRGB 做 gamma 反变换,直接拿 0~255 的编码值加权;先把 alpha 通道做了合成。本页固定用 WCAG 2.1 口径,中间量(线性 RGB、L)都列了出来,可手工复核。

这里算出的对比度能直接当无障碍合规结论吗?

不能,它只是单项数值。合规判定还要看实际字号字重、是否被图片或渐变覆盖、有无文本阴影、动态状态(hover / focus / disabled),以及非文本元素的 3:1 要求。要做成对检查并生成清单,请用颜色对比度检测;要排查色觉障碍下的可辨识度,请用色盲模拟。

相关工具