使用方法
- 用取色器点一下,或直接在文本框里填 hex 色值。#RRGGBB(六位)与 #RGB(三位缩写)都收,字母大小写随意:
#315fe8、#315FE8、#abc都能识别。页面打开时预置的是本站主色#315FE8。 - 点「查互补色」,或在色值框里按 Enter。左边色块是原色,右边是HSL 补角(保持 S 与 L 不变、色相旋转 180°),两块的色值同时以大字号显示。
- 看结果区下方的提示。它会给出 CIELAB 空间下的感知补色——那是一个完全不同的颜色:HSL 补角会改变明度,感知补色保持明度不变。如果提示里写了「已裁剪」,说明请求的色度超出了 sRGB 能表达的范围。
- 点「复制两个色值」把原色与补色的 hex 一次带走(TSV 两行,可直接粘进 CSS 变量表);点「载入示例」回到
#315FE8;点「清空」清掉色值框(此时会提示允许的格式,不会静默按黑色计算)。
这个互补色查询能解决什么问题
一是给已有品牌色找配对色。你手上有一个主色,需要一个在色相环上正对面的颜色做按钮底色、图表第二序列、或者深色模式下的强调色。直接取补角能得到数学上「最不同」的那个颜色。
二是避免「红配绿」这个经典错误。在美术的颜料色彩学(RYB 色轮)里红色的补色是绿色,但在屏幕的 RGB 加色混色里,红色(色相 0°)的补色是青色 #00FFFF(色相 180°)。这是本页最值得记住的一条:色轮有两种,别混用。本页所有计算都在 sRGB / HSL 空间进行。
三是判断某个配色是否真的「对比强」。HSL 补角保证色相差 180°,但不保证感知上的差异大——两色的明度可能接近(深蓝配深蓝),也可能差得离谱(正红配亮青,刺眼)。CIELAB 的 L* 与 C* 数据能告诉你实际差多少,页面上把两组结果的差值 ΔE76 直接算出来给你看。
四是为色盲用户检查配对色。约 8% 的男性有红绿色觉障碍,红绿配对对他们来说几乎一样。互补色(色相差 180°)在色觉障碍模拟下通常仍可区分,因为色相差远大于红绿轴的混淆范围——这一点比红绿配对安全得多。想自己验证,用「色盲模拟」把本页输出的两个色值丢进去看一眼。
本页不做这些事:不做三色配色方案(那是三角色色相分配,差 120° 不是 180°);不做邻近色(差 30°);不做渐变配色;不保证输出色通过 WCAG 对比度要求(补色只管色相,不管明暗)。要整套方案请用「邻近色颜色方案生成器」或「三角色颜色方案生成器」;要调明暗梯度请用「浅色颜色生成器」与「深色颜色生成器」;想知道某个色值的通用名称请用「颜色名字查询」。
原理:三种颜色空间下的「互补」不是同一个东西
第一种是 HSL 补角,公式是 H' = (H + 180) mod 360,S 与 L 保持不变。HSL 是 CSS Color 3 定义的颜色空间,转换分两步。RGB 转 HSL:先取 M = max(r,g,b)、m = min(r,g,b),L = (M+m)/2;S 分两段算——L < 0.5 时 S = (M−m)/(M+m),L ≥ 0.5 时 S = (M−m)/(2−M−m);H 看哪个通道最大:M=r 时 H = 60 × ((g−b)/(M−m) mod 6),M=g 时加 2,M=b 时加 4,最后把负值加 360。HSL 转 RGB:C = (1 − |2L−1|) × S,H' = H/60,X = C × (1 − |H' mod 2 − 1|),m = L − C/2,然后按 H' 落在 0~1 / 1~2 / 2~3 / 3~4 四个区间取 (C,X,0) / (X,C,0) / (0,C,X) / (0,X,C),最后每项加 m。关键取舍:取补角时只动 H,不动 S 与 L。这样做的理由是 HSL 的 H 维度是色相环上的角度,旋转它不改变「这个颜色有多鲜艳」和「有多亮」这两项感知属性;但代价是补色的明度可能与原色差很远(见下)。
第二种是 HSB / HSV 补色,算法与 HSL 完全不同。HSV 需要把 S 和 V 一起取反:H' = H + 180、S' = 1 − S、V' = 1 − V。实测差别极大:红色的 HSV 是 (0°, 100%, 100%),按这个规则补出的是 S'=0, V'=0 即黑色;而 HSL 补角给出的是 #00FFFF 青色。十二组实测里,HSL 补角与 HSV 补色没有一组相同。所以从 Photoshop 抄来的 HSB 数值不能直接套到 CSS 上——这是很多人算错的原因。
第三种是 CIELAB / LCH 感知补角,这是最「科学」但也最受限的一种。转换链路是四步:① sRGB 线性化,c ≤ 0.04045 时 c/12.92、否则 ((c+0.055)/1.055)^2.4;② 线性 RGB 乘 D65 矩阵得 XYZ,Y = 0.2126729R + 0.7151522G + 0.0721750B,白点 (0.95047, 1, 1.08883);③ 算 L* = 116f(Y/Yn) − 16、a* = 500(f(X/Xn) − f(Y/Yn))、b* = 200(f(Y/Yn) − f(Z/Zn)),其中 f(t) = t^(1/3)(t > 0.008856)否则 7.787t + 16/116;④ 转 LCH:C* = √(a*² + b*²)、h = atan2(b*, a*) 归一到 0~360°。CIELAB 的设计目标就是让数值距离接近视觉差异,所以在这里取补色的正确做法是只转色相 180°、保持 L* 与 C* 不变。红 #FF0000 的实测值是 L*=53.24、C*=104.55、h=40.00°;保持 L*=53.24 与 h=220.00° 时,sRGB 能表达的最大 C* 只有 31.06,远小于原来的 104.55——这就是「色域裁剪」,结果是 #008CA1。
为什么 CIELAB 补色要裁剪,为什么这件事很重要。sRGB 只是一个设备无关的显示约定,能表达的颜色是有限的三维立方体(1677 万色)。任何在 LCH 里合法但落在立方体外的颜色,转换回 sRGB 时三个通道里至少一个会超出 [0,1],只能被截断到边界。本页的做法是二分搜索最大可行色度(固定 L* 与 h,让 C* 从 0 逐步增大直到刚好越界),而不是简单地把超出的通道 clip 掉——后者会明显改变色相,产生偏色。实测差异:红色 HSL 补角是 #00FFFF(L*=91.11,被抬亮了 37.87),LCH 补色是 #008CA1(L*=53.31,基本保持原明度),两者 ΔE76 = 45.3——这是两个视觉上明显不同的颜色,选哪个取决于你要「色相对立」还是「感知对立」。
完整示例(数值均为实测)
页面默认色值是本站主色 #315FE8。实测结果:
- HSL(224.9°, 79.9%, 55.1%) → HSL 补角色相 404.9° ≡ 44.9°,输出 #E8BA31
- CIELAB L*=45.2、C*=80.8、h=294.4° → 感知补色 #5C7400(已裁剪)
- 两组结果的
ΔE76 = 46.5
这个例子把三种做法的差别显示得很清楚:#E8BA31 是个明亮的橙黄色,#5C7400 是个深橄榄绿。HSL 补角保留了饱和度但把明度从 55% 拉到了 50% 附近、且色相落在暖色区;LCH 补角把明度钉在 L*=45.2 几乎不动,但因为要保住 C*=80.8 的高饱和度,色相只能落在绿到黄之间。如果你在深色界面上做强调色,#E8BA31 在深底上对比度更好;如果你要的是「同样深、同样艳、方向相反」,#5C7400 才是对的。
再看红色这个最经典的例子。红色 #FF0000 的 HSL 补角是 #00FFFF 青色,而 CIELAB 感知补色是 #008CA1 蓝绿色——两者差 ΔE76 = 45.3。中文命名上要注意:红色的互补色是青不是绿(H=0° → H=180° = cyan);绿色的补色是品红(H=120° → 300° = magenta);蓝色的补色是黄(H=240° → 60° = yellow)。CSS Color 4 里这三个名字分别对应 #00FFFF、#FF00FF、#FFFF00。
十二组实测对照表与输入范围
下表是十二个色值在两种算法下的输出。「已裁剪」列标记的是那种「保持 L* 与 C*、只转色相」的请求落在 sRGB 色域外、必须二分收敛到边界的颜色;ΔE76 是两组补色之间的 CIELAB 欧氏距离,数值越大说明两种算法分歧越厉害:
| 原色 | H | S | L | HSL 补角 | LCH 感知补色 | 已裁剪 | ΔE76 | |
|---|---|---|---|---|---|---|---|---|
| #FF0000 | 0° | 100% | 50% | #00FFFF | #008CA1 | 是 | 45.3 | |
| #00FF00 | 120° | 100% | 50% | #FF00FF | #F1D1FF | 是 | 93.8 | |
| #0000FF | 240° | 100% | 50% | #FFFF00 | #2C5600 | 是 | 85.6 | |
| #FFFF00 | 60° | 100% | 50% | #0000FF | #F5F6FF | 是 | 144.8 | |
| #FF00FF | 300° | 100% | 50% | #00FF00 | #00A850 | 是 | 62.8 | |
| #00FFFF | 180° | 100% | 50% | #FF0000 | #FFDEDF | 是 | 100.8 | |
| #315FE8 | 224.9° | 79.9% | 55.1% | #E8BA31 | #5C7400 | 是 | 46.5 | |
| #8B4513 | 25.0° | 75.9% | 31.0% | #13598B | #00607A | 是 | 17.4 | |
| #1E90FF | 209.6° | 100% | 55.9% | #FF8D1E | #9B9200 | 是 | 48.4 | |
| #FFC0CB | 349.5° | 100% | 87.6% | #C0FFF4 | #95DED6 | 否 | 12.5 | |
| #2F4F4F | 180.0° | 25.4% | 24.7% | #4F2F2F | #5D4344 | 否 | 8.9 | |
| #7F7F7F | 0° | 0% | 49.8% | #7F7F7F | #7F7F7F | 否 | 0.0 |
从这张表能读出三条规律:① 纯色与高饱和色的分歧最大——黄色的 ΔE76 = 144.8 是全表最高,因为黄色的 L* = 97.1 已经接近白,转 180° 之后请求的高饱和浅色几乎无法在 sRGB 里实现,只能大幅削色度;② 低饱和色的分歧最小——粉色 #FFC0CB 只有 12.5,深灰 #2F4F4F 只有 8.9;③ 灰阶完全没有色相——#7F7F7F 的 S = 0%,此时 HSL 里 H 不参与计算(公式中 M−m = 0),补色就是它自己,ΔE76 = 0。这不是 bug,是「无色可补」的必然结果。
三位缩写写法会先展开成六位再算,实测三组:#abc → #AABBCC(H=210°、S=25%、L=73.3%)→ 补角 #CCBBAA;#369 → #336699(H=210°、S=50%、L=40%)→ 补角 #996633;#963 → #996633(H=30°、S=50%、L=40%)→ 补角 #336699。最后一组正好互为补角,可用来验证展开逻辑没写反。
边界、精度与常见误读
- 只收
#RGB与#RRGGBB两种写法,不收八位含 alpha 的#RRGGBBAA。带 alpha 的补色没有定义——透明度不参与色相计算,四个通道变六个通道,HSL 补角公式直接失效。本页遇到八位会明确报错并让你去掉后两位,而不是悄悄丢掉 alpha。要带透明度的颜色请用「Transparent颜色计算器」。 - 色相范围是 [0, 360),360° 等价于 0°。所以
#315FE8的H=224.9°补角是404.9°,取模后是44.9°。对称地,359.9°的补角是179.9°——色相环是首尾相接的,没有「最后一个色相」这种特殊位置。 S = 0%、L = 0%或L = 100%时补色等于原色。实测#000000(L=0%)、#808080(S=0%)、#FFFFFF(L=100%)三者的补色都是自身。此时页面上仍然会显示结果(不静默失败),但会在提示里说明「该色无色相,补色等于原色」——因为把它们当成 bug 反而是误解。- CIELAB 转换有 8 位量化误差,这是精度上限。页面用 Lindbloom 标准的 D65 矩阵对(含 7 位小数)做 XYZ 往返,抽样 4096 色实测最大往返误差
2.07 × 10⁻⁶,远小于 8 位量化的1/255 ≈ 3.9 × 10⁻³。所以真正的误差来源是最后一步「转成 8 位通道时的四舍五入」,不是矩阵本身。想避免量化误差就用 16 位色彩空间或 ICC 配置文件,那是设计软件的事。 - HSB 补色与 HSL 补色在十二组实测里无一相同。如果你从 Photoshop 拿 HSB 数值,务必确认是 RGB 直算的 HSB(Adobe 传统定义)还是 gamma 校正的 HSV——两者对
S的定义不同,补色结果也不同。本页只做 HSL 与 CIELAB 两套,不提供 HSB 输出。 - 互补色不保证 WCAG 对比度达标。补角只管色相,不管明暗。红
#FF0000与青#00FFFF互为补色,但正文用红、青配白底都达不到 AA 级对比度。补色适合做色块与装饰,做正文文字必须另配明度。颜色对比度检测能验这个。 - 青是 cyan、品红是 magenta,别用「蓝绿」「紫红」代替。CSS Color 4 定义的三个加色原色是
cyan = #00FFFF、magenta = #FF00FF、yellow = #FFFF00。中文里 cyan 习惯叫「青」,magenta 叫「品红」或「洋红」;用「蓝绿」「紫红」虽然不影响计算,但会让团队沟通时对不上号。
常见问题
为什么红色的互补色是青色不是绿色?
因为有两种色轮。在美术的颜料色彩学(RYB 色轮)里红色对绿色,那是颜料的减色混色,油画里红和绿放一起确实互相削弱。但在屏幕的 RGB 加色混色里不一样:色相 0° 是红,转 180° 到 180° 就是 cyan,实测 #FF0000 的 HSL 补角是 #00FFFF。网页、UI、图表全是加色,所以本页一律按 RGB 算。你在设计工具里看到「红配绿」的说法,那是在说印刷品。
HSL 补角和 CIELAB 感知补色,我该用哪个?
看你需要哪种「对立」。要色相环上的正对面(比如图表里两组数据要明显区分、logo 需要对比强烈的配色),用 HSL 补角,它保证色相差正好 180°。要感知上的等强度对立(比如深色界面上找一个不刺眼又不沉闷的强调色),用 CIELAB 感知补色,它保持明度与彩度不变。两者在纯色上差得很远——黄色的 ΔE76 高达 144.8,视觉上完全不是一回事。本页两个都给出来,你自己挑。
「已裁剪」是什么意思?我的颜色被改了吗?
没改错,但你要求的那组 LCH 参数在 sRGB 里不存在。sRGB 只能表达 1677 万种颜色,构成立方体;当你要求「保持 L*=53.24、C*=104.55、色相转到 220°」时,落点在立方体外面。本页的做法是固定明度与色相,二分搜索出刚好在边界内的最大彩度(红色的结果是 C*=31.06,比原值低得多),所以叫「裁剪」。标记为「已裁剪」表示彩度被降低了;标记「否」表示原色度完整保留。
灰色的互补色就是它自己,这是出错了吗?
不是出错。HSL 公式里 S = (M−m)/(M+m),灰色三个通道相等所以 M−m = 0,S = 0%;而 H 的计算全部除以 M−m,分母为 0 时 H 无意义。灰阶在色相环上没有位置,所以「转 180°」这个操作对它没有意义,补色自然等于原色。实测 #000000、#808080、#FFFFFF 三者都是如此,CIELAB 侧 C* = 0.00 也是零。页面上会明确告诉你「无色相」,不会假装算出了什么。
为什么 Photoshop 里同一个颜色算出的补色和这里不一样?
最可能是三点之一。一,PS 用的是 HSB 或 HSL 面板,而补色规则不同:HSB 要 S→1−S、V→1−V,HSL 只转 H。实测红色的 HSB 补色是黑色(S=0,V=0),HSL 补色是青色,差得极远。二,PS 的「色轮」可能是 RYB 模式(绘画默认),转 180° 得到的是颜料补色而不是 RGB 补色。三,PS 的滑块是 0~255 取整,累积误差与这里的 8 位量化同级。如果你需要两边一致,先确认工具用的是 RGB/HSL 模式并统一到 sRGB 配置文件。
三位缩写和六位写法算出来一样吗?
一样,因为三位会先展开成六位:#abc 展开为 #AABBCC(每位数字重复两次)。实测 #abc(H=210°、S=25%、L=73.3%)的补角是 #CCBBAA,#AABBCC 的补角也是 #CCBBAA。所以用哪种写法不改变结果,只是六位能表达 1677 万色、三位只有 4096 色。注意展开规则是按位重复,#369 展开是 #336699 而不是 #336699 之外的任何值——实测 #369 与 #963 互为补角,可用来验证没写反。
互补色能用在我网站的文字上吗?
不建议直接用。补色只解决色相对立,不管明暗对比。红 #FF0000 配青 #00FFFF 互为补色,但在白底上红色的对比度约 3.9:1、青色约 1.25:1,都达不到 WCAG AA 对正文要求的 4.5:1(大字号要 3:1)。把补色当色块与强调元素用没问题,做正文文字必须用「颜色对比度检测」或「调色工具」另行验证并调整明度。
我输入的色值会被上传或保存吗?
不会。颜色转换由页面内的 JavaScript 完成,只用到几条乘法和一次二分搜索,没有任何 fetch 或 XMLHttpRequest 调用,也不写 localStorage;刷新后色值框回到 #315FE8。想自己确认,打开开发者工具的 Network 面板,改动色值时观察是否有请求发出——不会有。
相关工具
- RGB转HSL转换器:只做 RGB→HSL 单向转换,用来核对本页给出的 H、S、L 三项。
- HSL转RGB转换器:反向验证补角算出的 RGB 是否与页面色块一致。
- 十六进制转HSL转换器:从 hex 直达 HSL,少一步 RGB 解析。
- 三角色颜色方案生成器:要的是色相差 120° 的三方配色(互补色是 180°,两者不同)。
- 邻近色颜色方案生成器:色相差 30° 的和谐配色,视觉上比互补色柔和得多。
- 颜色对比度检测:补色定完之后,验一下能不能当文字色用。
- 颜色工具:查看全部颜色工具。