使用方法
- 页面打开时已经是一组示例:起点
#2563EB、终点#F59E0B、停止点数 5、方向角 90 度、插值空间 OKLCH、类型 linear-gradient。预览条、CSS 代码框、下面「完整示例」和对照表用的都是这一组参数。 - 改颜色两条路:拖拾色器,或在旁边的文本框里键入六位十六进制值(
#2563EB与2563EB都接受,三位缩写不接受)。起点与终点任意一处改动都会立即重算整条色带。 - 调停止点数(2~9 的整数):它决定色带上显式写出的色标个数,位置按
100 / (n − 1)等距排布。5 个点就是 0%、25%、50%、75%、100%。 - 调方向角(0~360 的整数):只对 linear-gradient 生效。0 度指向正上方、90 度指向正右方、180 度向下、270 度向左,角度按顺时针增加。
- 选插值空间:sRGB 直接插值最接近很多浏览器里无提示的默认行为,HSL 走最短色相路径,OKLCH 在感知均匀的 Oklab 空间里插值。三个空间算出来的中间色差别很大,可以逐个切过去看。
- 选渐变类型:linear / radial / conic 三种,CSS 代码框会同步换成对应的函数写法。radial 与 conic 不使用方向角,角度框会被忽略,页面右下角的提示会说明这一点。
- 点「复制 CSS」把两行代码拿走(第一行是兜底纯色,第二行是渐变);「反向渐变」交换起点与终点;「随机配色」从色相环上随机取一对颜色;「载入示例」还原默认值。
渐变色生成器能解决什么问题
一是把「渐变中间发灰」这件事定位到具体色值。蓝色到橙黄是最常见的一对互补色,在 sRGB 里直接插值,50% 的位置会得到 #8D817B——一个饱和度只有 0.07 的脏灰色,视觉上像一块被洗掉的污渍。本工具把同一对颜色在 OKLCH 空间里插值,50% 的位置是 #DF57A9,饱和度保持在 0.55 上下,色带从头到尾都是一条干净的弧线。切换插值空间就能直接看到两条色带的差别。
二是给出可以直接粘进样式表的代码,而不是一张图。输出里除了 background-image 那行渐变,前面还有一行 background-color 纯色兜底——渐变渲染失败时至少还有一个品牌色,这是很多手写渐变的项目会漏掉的一步。
三是把中间色逐档列出来。设计师给的往往只有两端色,开发需要中间色时只能靠取色器在截图上一格一格吸。对照表把三种空间、每个停止点的 HEX、RGB、HSL、相对亮度全部列出来,要哪一档直接抄。
四是验证一套配色能不能当色阶用。做数据可视化或多层背景时,需要一条亮度递增的连续色带;把两端的明度拉开、切成 9 个停止点,看对照表里相对亮度那一列是否单调递增就够了,比肉眼判断可靠。
这个渐变色生成器不做这些事:不导出 PNG 图片(输出的是 CSS 代码而不是位图)、不做多段渐变(一条色带只有一对端点色)、也不做色盲与对比度检查——文字压在色带上能不能看清,请用页面底部的「颜色对比度检测」逐档验证。
原理和变量:sRGB、HSL、OKLCH 三种插值
所有渐变生成器都要回答同一个问题:两个端点色之间,第 t 档(t 从 0 到 1)取什么颜色?区别只在于「在哪个空间里做线性插值」。本页实现三种,并给出每一步的换算。
sRGB 直接插值。把两个端点拆成 R、G、B 三个 0~255 的数,逐通道按 c = c1 + (c2 − c1) × t 插值,再拼回去。这是最省算力的做法,也是很多浏览器在 linear-gradient 里实际使用的做法。它的问题不在于「不准确」,而在于 sRGB 是 gamma 编码空间——两个数值的中点并不等于视觉上的中点。示例这一对色在 50% 处得到 #8D817B,相对亮度 0.2279,比两端都出现了一个明显的灰化。
HSL 插值。先把端点转到 HSL,色相 H 走最短路径:当两个色相差的绝对值超过 180 度时,把方向反过来算(等价于 delta = ((h2 − h1 + 540) mod 360) − 180),否则从蓝 221 度一路顺时针走到橙 38 度要绕 183 度,会经过绿色;走反向的 176 度则经过品红。示例的色相差是 −183.5 度,所以工具选了反向路径,50% 落在 #F018CE。S 与 L 则各自线性插值。HSL 的 L 只是「最大最小通道的平均值」,不是感知亮度,所以它在明度上仍会跑偏。
OKLCH 插值。先把 sRGB 做 gamma 反变换得到线性 RGB(分界点取 0.04045,这是 IEC 61966-2-1 的现行写法),再用三组 LMS 矩阵和立方根变换到 Oklab,然后取成极坐标 L、C、H:L 是感知亮度,C 是色度(饱和度),H 是色相角。插值时 L 与 C 线性、H 走最短路径,最后逆变换回线性 RGB 并做 gamma 编码。Oklab 由 Björn Ottosson 在 2020 年提出,设计目标就是让这个空间里的欧氏距离尽量接近人眼感知的色差,所以它的「中点」看起来才真的是中间。渐变色生成器把 OKLCH 设为默认空间,原因就在这里:示例的 OKLCH 路径在 50% 给出 #DF57A9。
正反两个方向的矩阵都写在这里,方便你拿别的工具复核。sRGB 线性 → Oklab:l = 0.4122214708R + 0.5363325363G + 0.0514459929B,m = 0.2119034982R + 0.6806995451G + 0.1073969566B,s = 0.0883024619R + 0.2817188376G + 0.6299787005B,取三者的立方根得 l′、m′、s′,再 L = 0.2104542553l′ + 0.7936177850m′ − 0.0040720468s′、a = 1.9779984951l′ − 2.4285922050m′ + 0.4505937099s′、b = 0.0259040371l′ + 0.7827717662m′ − 0.8086757660s′。反向则是 l′ = L + 0.3963377774a + 0.2158037573b(m′、s′ 同理,系数分别是 −0.1055613458 / −0.0638541728 与 −0.0894841775 / −1.2914855480),立方回去后 R = 4.0767416621l − 3.3077115913m + 0.2309699292s、G = −1.2684380046l + 2.6097574011m − 0.3413193965s、B = −0.0041960863l − 0.7034186147m + 1.7076147010s。
停止点位置公式。第 i 个停止点(i 从 0 开始)的位置是 i / (n − 1) × 100%。n = 2 时只有 0% 与 100%;n = 5 时步长 25%;n = 9 时步长 12.5%,依次是 0%、12.50%、25%、37.50%、50%、62.50%、75%、87.50%、100%。CSS 里的百分比是沿渐变轴的投影位置,不是沿屏幕距离。
角度约定。CSS 的渐变角度以「向上」为 0 度、顺时针增加,所以 0deg 等价于 to top、90deg 等价于 to right、180deg 等价于 to bottom、270deg 等价于 to left。新手常把 90deg 当成「从左到右」——那是 to right 的含义没错,但它的角度值就是 90,而「从左上到右下」是 135deg,不是 45deg。
完整示例
示例参数与默认值一致:起点 #2563EB、终点 #F59E0B、5 个停止点、90 度、OKLCH 插值、linear-gradient。先把两端转成中间量,再列三个空间的实际取色。
- 起点
#2563EB:HSL 是221.2, 0.832, 0.533;Oklab 是L = 0.5461, a = −0.0267, b = −0.2135,换算成 OKLCH 即L = 0.5461, C = 0.2152, H = 262.88°;WCAG 相对亮度 0.1532。 - 终点
#F59E0B:HSL 是37.7, 0.921, 0.502;Oklab 是L = 0.7686, a = 0.0561, b = 0.1548,即L = 0.7686, C = 0.1647, H = 70.08°;相对亮度 0.4389。 - 色相差:HSL 口径为 −183.5 度(超过 180,反向走 176.5 度);OKLCH 口径为 +167.2 度(不到 180,正向走)。两个空间给出的「最短路径」方向一致,但走过的角度不同。
三空间在 25% / 50% / 75% 三个位置的实际取色:
| 位置 | sRGB 直接插值 | HSL 插值 | OKLCH 插值 |
|---|---|---|---|
| 25% | #5972B3(L 0.1741) | #761FED(L 0.1095) | #9D57E0(L 0.1937) |
| 50% | #8D817B(L 0.2279) | #F018CE(L 0.2363) | #DF57A9(L 0.2537) |
| 75% | #C18F43(L 0.3139) | #F2122A(L 0.1948) | #FE6F60(L 0.3328) |
最该看的是 50% 那一列:sRGB 给出 #8D817B,HSL 饱和度只有 0.07,肉眼看接近一块脏灰;HSL 给出 #F018CE,是最短路径绕到品红的结果,起点到终点之间亮度先降后升(0.1532 → 0.1095 → 0.1948);OKLCH 给出 #DF57A9,相对亮度 0.2537,是三者里唯一在整条色带上保持亮度单调递增的(0.1532 → 0.1937 → 0.2537 → 0.3328 → 0.4389)。
于是默认输出的 CSS 是:
把插值空间换成 sRGB,同一组参数变成 #2563EB 0%, #5972B3 25%, #8D817B 50%, #C18F43 75%, #F59E0B 100%;换成 HSL 则变成 #2563EB 0%, #761FED 25%, #F018CE 50%, #F2122A 75%, #F59E0B 100%。三条色带的端点完全相同,中间三个色标一个都不一样。
输入范围与对照表
本页接受的输入范围,以及越界时的处理:
- 起点色 / 终点色:六位十六进制,允许带或不带
#,大小写都认。三位缩写、少于六位、出现G之后的字母、空值都会被拒绝,并明确指出是哪一个框。 - 停止点数 2~9 的整数:2 是两个端点,9 是每 12.5% 一个色标。少于 2 无法构成渐变;超过 9 会让 CSS 变得很长而视觉收益递减。
- 方向角 0~360 的整数:360 与 0 等价(CSS 允许两者,本页照原样输出)。小数和负数一律拒绝——负角度虽然 CSS 接受,但容易和「逆时针」的直觉混淆,不如直接写 360 减去它的值。
- 渐变类型与插值空间:下拉选择,不存在非法输入。radial 与 conic 会忽略角度框,页面会提示这一点而不是静默丢弃。
下表把三种空间在「几对常见端点色」上的 50% 取色放在一起。这几对色的共同点是:sRGB 直连的中间都会明显偏离视觉预期。
| 端点对 | 50% · sRGB | 50% · HSL | 50% · OKLCH |
|---|---|---|---|
| #0000FF → #FFAA00 | #805580 | #FF00AA | #E728A0 |
| #2563EB → #F59E0B | #8D817B | #F018CE | #DF57A9 |
| #FF0000 → #00FF00 | #808000 | #FFFF00 | #F99500 |
| #000000 → #FFFFFF | #808080 | #808080 | #636363 |
最后一行很能说明问题:黑白渐变在 sRGB 与 HSL 里中点都是 #808080,这是三个通道各取一半的结果;而 OKLCH 给出的中点是 #636363,明显更深。#636363 的 Oklab 亮度正好是 0.5,也就是这个空间里真正的感知中点,#808080 的 Oklab 亮度是 0.5999。做「黑到白」的进度条或骨架屏时,这个差别一眼可见——这类只能靠对照表才看得出来的差异,正是渐变色生成器把三个空间并排列出的意义。
再补一张停止点数与位置对照:
| 停止点数 n | 步长 100/(n−1) | 各停止点位置 | 对照表行数 3n |
|---|---|---|---|
| 2 | 100% | 0%, 100% | 6 |
| 3 | 50% | 0%, 50%, 100% | 9 |
| 5(默认) | 25% | 0%, 25%, 50%, 75%, 100% | 15 |
| 9 | 12.5% | 0%, 12.5%, 25%, 37.5%, 50%, 62.5%, 75%, 87.5%, 100% | 27 |
结果边界与舍入误差
渐变色生成器在下面几个地方刻意做了取舍,知道边界在哪,色带才不会用错地方。
- 中间色都要量化到 8 位。OKLab 里的插值结果是浮点数,写进 CSS 前必须四舍五入成六个十六进制字符,所以色带上每一点都有一个不超过 1/255 的量化误差。这也是为什么同样一对颜色,不同工具算出的中间色偶尔会差一个色阶。
- 两个空间的线性化分界点不一样。OKLab 那一侧用的是现行 sRGB 规范的 0.04045,而对照表里「相对亮度 L」这一列用的是 WCAG 2.1 的 0.03928。两者相差 0.00117,只影响归一化后正好落在这条窄缝里的分量,对结果的影响通常出现在小数点后第三位,但两套公式确实不是同一个。
- 超出 sRGB 色域的 OKLab 值会被夹紧。两端色本身都在色域内,但中间点的色度 C 可能落在 sRGB 之外(尤其是经过很饱和的青色或品红时)。本页的做法是把逆变换后的线性 RGB 直接夹到 0~1 再做 gamma 编码,等价于做一次通道裁剪,而不是按色相投影回色域边界。裁剪会让那一小段色带的色相微微偏移,这是感知均匀插值的常见代价。
- 色相在 C 接近 0 时没有意义。当某个端点是黑、白或纯灰时,它的 a、b 都是 0,色相角在数学上未定义(本页按 0 处理)。此时无论走哪条路径,结果都只由另一端的色相决定,中间色看起来仍然是灰的,这是正常现象而不是 bug。
- radial 与 conic 不使用方向角。radial-gradient 的色标位置沿半径分布,conic-gradient 沿角度分布,方向角对它们没有意义。工具会在提示里说明角度被忽略,而不是假装它生效了。conic-gradient 如果要首尾无缝衔接,需要自己把终点色改回起点色,本页不会自动补这一档。
- 浏览器端还会再做一次插值。CSS 渲染渐变时,浏览器在相邻两个色标之间重新插值一次,而且各家的做法不完全一致(部分引擎已经支持在 sRGB 之外的色彩空间里插值)。本页给出的是显式色标,色标位置上的颜色是确定的;两个色标「之间」的那几十个像素由浏览器决定,不要拿它当精确色卡用。
- 渐变不能替代对比度检查。色带是一段连续变化的底色,文字压在上面时,只要有一小段没通过门槛,整条色带上的文字就都有问题。把停止点的色值逐档拿到「颜色对比度检测」里过一遍,比只看两端色可靠。
常见问题
为什么 sRGB 直连会让蓝色到橙色中间发灰?
因为 sRGB 把每个通道存成 gamma 编码值,数值上的「一半」并不是亮度上的一半。蓝色是 #2563EB(R 37、G 99、B 235),橙色是 #F59E0B(R 245、G 158、B 11),逐通道取中就是 R 141、G 129、B 123——三个分量被拉到了几乎相等的水平,于是变成灰色。正确做法是先线性化到光强、在感知均匀的空间里插值,再编码回来,也就是 OKLCH 那条路径。
OKLCH 和 OKLab 是一回事吗?
是同一个空间的两种写法。Oklab 用直角坐标(L、a、b)表达,OKLCH 把它转成极坐标(L、C、H),C 是色度、H 是色相角。做插值时用极坐标更顺手,因为可以单独控制「色相怎么走」和「饱和度怎么变」;做色差计算时用直角坐标更直接,欧氏距离就是色差。本页的 OKLCH 插值内部就是把两端转成极坐标、分别插值后再转回去。
「最短色相路径」是谁定的?我可以强制走另一边吗?
最短路径是 CSS Color 4 规范里对色相插值给出的默认行为(hue interpolation 的 default 关键字),指的是把色相差归一到 −180 到 180 之间。本页照此实现,所以示例里蓝到橙走了反向的 176.5 度而不是正向的 183.5 度。想强制走另一边,把起点和终点互换即可——反向走出来的路径就是原来的另一条。
0deg 到底朝哪?为什么我感觉方向反了?
CSS 的渐变角度以「向上」为 0 度,顺时针为正,所以 0deg 是指向上方(等价于 to top),色标从下往上排列;90deg 指向右方。很多人凭直觉以为 0 度是「从左到右」,于是把横向渐变写成了 0deg,结果拿到一条竖直渐变。记住 to <方向> 这种写法不需要记角度,不涉及动画时优先用它。
两个色标之间的颜色,浏览器算出来和我算的为什么对不上?
因为你在两个色标之间又插了一次值,而这次的插值由浏览器决定。本页给出的色值只在色标位置上精确成立;色标之间的那一段,浏览器可能在线性 RGB 里插,也可能在 gamma 编码的 sRGB 里插,不同引擎的历史行为并不统一。需要精确控制时,把停止点数提高到 9,让色标密到肉眼看不出中间段。
停止点数越多渐变越平滑吗?
不会更平滑,只是更精确。linear-gradient 本身在两个色标之间就是线性插值,多加色标等于把同一条折线画得更细;真正影响「顺不顺」的是插值空间与端点色的选择。把停止点数从 5 提到 9,唯一的变化是你在色带中段少了一点「不知道具体是什么色」的区域,以及配合色标位置做动画时能更精确地停住。
为什么输出里有一行 background-color?
那是兜底色。少数老旧引擎或某些打印场景不会渲染渐变,此时 background-image 整行被忽略,元素就会变成透明的;前面先声明一个 background-color 等于起始色,至少还能看到一个统一的品牌色。这不是过时的兼容写法,而是渐变背景的常规防御措施,成本只有一行代码。
渐变的中点颜色和「混合两个颜色」是一回事吗?
不是。混色工具(例如 sRGB 的 alpha 混合)算的是两个颜色按比例叠加后的实际结果,参与运算的是带 alpha 的分量;而渐变插值算的是把 t 从 0 推到 1 时色带上的取样点。两者在 sRGB 里逐通道计算时结果常常一致,但一旦进入 HSL 或 OKLCH,或者两端带透明度,就会分道扬镳。要算叠加结果请用「调色工具」,要做色带请用本页。
相关工具
- 颜色对比度检测:把色带上每个停止点的色值过一遍 WCAG 阈值,确认压在上面的文字够不够清楚。
- 颜色配色生成器:一次给出成套的主色、辅色与强调色,选定后再回到本页生成渐变。
- 随机颜色生成器:快速抽一个颜色作为起点或终点,适合「先随便看看」的阶段。
- RGB转HSL转换器:核对对照表里的 HSL 那一列,看看 HSL 插值到底改了哪些分量。
- 颜色选择器:单独查看某个中间色的线性 RGB、相对亮度与 HSL 往返误差。
- CSS长方体阴影生成器:渐变之外的另一类视觉层次写法,两者经常搭配使用。
- CSS圆角生成器:把渐变条的圆角半径算准,避免色带两端出现硬边。
- 生成器:查看全部生成器工具。