首页 /配色指南 /你的浅色背景其实不是带色的

你的浅色背景其实不是带色的

设计交接里最常见的一句话是「背景用主色的 5%」。库内 100 套配色里,按 HSL 口径有 38 套的背景算带色,按色度口径只有 9 套看得出来。差的那 29 套不是配色做错了,是拿错了衡量工具。

最后更新:2026-11-02

「主色的 5%」这句话里,5% 没有单位

这句话的问题不在数字,在单位。指的是不透明度,就是用白色稀释主色;指的是 HSL 饱和度,是另一件事;指的是亮度偏移,是第三件事。三种做法算出来的颜色,视觉强度可以差三倍以上,而交接文档里写的都是「5%」。

更麻烦的是多数设计工具显示的饱和度是 HSL 口径。HSL 的饱和度定义成「相对当前明度的纯度」,明度越接近 100,它越不管用。下面这组数字来自库内 100 套配色的背景色,两种口径给出的结论方向相反。

同一批底色,两个口径差四倍

判定口径判定为「带色」得到的结论
HSL 饱和度 > 1238 套近四成配色的底是带色的
Lab 色度 C* ≥ 29 套不到一成看得出来

把这 38 套按色度重算,中位只有 1.03。这个数值意味着什么:把它的颜色和纯白并排放,绝大多数人分不出来。而它们的 HSL 饱和度中位是 9.1,其中还有几套写着 100。

全库的色度分布更极端:C* 小于 1 的有 75 套(75%),1 到 2 之间有 16 套(16%),达到 2 的只有 9 套(9%)。中位数 0.63。

也就是说,一个标着「带一点主色」的底色,九成情况下用户看到的就是白色。这不是坏事,但如果设计意图是「看得出分区」,那这个意图没有实现。

为什么 HSL 饱和度在浅色区会失效

HSL 的 S 是相对量:它描述颜色离开中性轴多远,而这个距离在明度逼近白点时被压缩。当 L 到 98,RGB 三个通道都挤在 250 以上,最大值与最小值只差个位数,饱和度再高也没有空间可以表现。

用同一个色相 h=30 做一组演示,每一行固定明度,把饱和度从 30 拉到 90:

明度 L色度 C*(依次为 S=30 / 60 / 90)
98%1.1 / 1.8 / 2.9
95%2.5 / 4.6 / 7.1
90%4.8 / 9.9 / 14.5

表格右侧每行三个数字是色度 C*,依次对应 S=30 / 60 / 90。看两件事。

第一,L=98 时把饱和度从 30 拉到 90,色度只从 1.1 到 2.9,仍然在「看不出来」的区间。饱和度翻了三倍,视觉上几乎没有变化。

第二,什么都不改,只把明度从 98 降到 90,S=30 的色度就从 1.1 涨到 4.8,超过 L=98 时 S=90 的四倍。换句话说,浅色区的带色强度主要由明度决定,饱和度是次要变量。想要「加一点点色」,往下调明度比往上加饱和度有效得多。

同一个 5%,两种实现差三百多倍

这句话真正的危险在于:两种都自称「按主色的 5% 来」的实现,结果根本不在一个量级。用库内一个真实主色 #2563eb 各做一次:

实现得到的颜色色度 C*
A:主色 5% 不透明度,叠在白底上#f4f7fe3.72
B:饱和度取主色的 5%,明度提到 98#fafafa0.01

A 落在「看得出带色」的窗口里,可以直接用。B 是 #fafafa,色度 0.01,和纯灰没有区别,做了等于没做。两者相差 323 倍。

这不是谁对谁错的问题。A 碰巧好用,是因为用白色稀释在降低饱和度的同时也抬高了明度,两个变量一起动;B 只把饱和度降下来、明度原地不动,于是什么也没发生。同一个百分比、同一句需求,一个落在窗口内,一个落在窗口外,而设计稿上写的是同一行字。

能用的窗口

按库内实测和上面的演示,色度可以分成四档,每一档对应一个具体用途:

色度 C*观感适合放哪里
< 1就是白或灰,换掉也不会被察觉想要纯白就直说,不必绕成「主色的 2%」
1 ~ 2说不出哪里不一样,但换掉能感觉到大面积页面底
2 ~ 4看得出是带色的,但仍算克制分区底、卡片底、表头
> 4明确有颜色,不再是「一点点」只适合小面积,或者深色底

库内达到 2 的 9 套里,最高的是 #0f0d1a,色度 8.4,但它是一套深色底。浅色区里最高的一套不到 7,而且已经在「明显带色」那一档。这说明浅色区能用的窗口很窄:2 到 4 之间。

深色底是另一回事

库内 2 套深色底的色度是 7.0 到 8.4,比浅色区的上限还高,但看起来并不刺眼。原因还是明度:深色区域里人眼对色彩的分辨力更弱,同样的绝对色差要用更大的色度才等价,所以深色底反而容纳得下更多颜色。

另一组对照能说明同一件事:库内正文文字色的色度中位是 4.6,是背景色中位 0.63 的七倍多。文字是界面上面积最小、最必须被读到的元素,它的色度必须够强;底色是最大面积、最不必被注意的元素,它的色度必须够弱。同一套规则在两端给出相反的数值。

所以「底色的色度」没有统一答案,它取决于面积。深色底、小面积、需要被注意,都往高走;浅色底、大面积、需要退到后面,都往低走。

在项目里怎么落地

  1. 用色度判断,不要用 HSL 饱和度。C* = √(a² + b²),在 CIELAB(D65 白点)下算。任何颜色库都有现成实现,二十行代码。HSL 的饱和度只在中间明度区间可以粗略当指标用,而底色恰好不在那个区间。
  2. 浅色底想要「看得出带色但不抢眼」,把明度压在 95 到 97、色度定在 2 到 3。这两个数字是互相关联的:明度越低,同样的色度越明显。先定明度,再调色度。
  3. 交接时给绝对色值,不给百分比。「主色 5%」到实现端会变成三四种不同的颜色,因为每个人对 5% 的理解不一样。给 #f7f8fa,并且注明它是色度 1.8 的中性偏蓝底,没有歧义。

第三条最容易被跳过,但它决定前两条有没有用。一个能被复现的数值,比一个听起来精确的百分比可靠。

数据怎么来的

上面每一个数字都由构建期的 src/lib/guide-stats.mjs 从库内 100 套配色的 bg 字段现算,CIELAB 转换在 src/lib/lab.mjs,用 D65 白点与 sRGB 标准矩阵。色度分档的阈值(1 / 2 / 4)是在这套数据上定的,不是引用某个标准:没有标准规定「底色该有多少色度」,只能从实际分布里找窗口。

演示表格里的九个色度值由公式在构建期生成,色相固定 h=30,不依赖具体配色,任何时候重算都是同一组数字。

相关:卡片与分割线为什么看不见讲的是另一类「数值很低但确实存在」的角色;编辑标准记录了三道闸门与计算口径。