不喜欢广告? 无广告 今天

OKLCH 与现代 CSS 颜色 — 为什么你的配色方案在某些浏览器中看起来异常

更新于

RGB 和 HSL 是为阴极射线管显示器设计的。OKLCH 修复了感知均匀性,color-mix() 改变了渐变混合,而相对颜色语法无需预处理器即可启用。

OKLCH与现代CSS颜色——为什么你的配色在某些浏览器中看起来不同 1
广告 移除?

你为主要按钮选择了蓝色,在浏览器中看起来很合适。你在一台较新的MacBook Pro上打开预发布环境,看起来……尚可,只是略显平淡。你的设计师从iPhone上发送了一张截图,同样的按钮看起来明显更鲜艳。相同的十六进制代码,不同的显示效果。

这是P3色域的差距。实际上,这是你一直使用的CSS颜色模型失效的最不重要部分。更大的问题是HSL背后的数学原理。

sRGB色域的上限

每一个你曾经写过的十六进制颜色和 rgb() 你曾经写过的值都存在于sRGB色域中——这是一种1996年为CRT显示器设计的标准。sRGB覆盖了人类可见色域的大约35%。自2017年起,所有iPhone都使用P3色域,自2016年起大多数MacBook也采用了P3色域,其覆盖范围约为45%。

当你写 #3b82f6时,该颜色被限制在sRGB范围内。在P3显示设备上,浏览器理论上可以渲染更饱和的蓝色——但你的CSS并未要求这一点。你默认忽略了显示器的潜力。

要直接访问P3颜色,你需要使用 color(display-p3 0.2 0.4 0.9)。这可行。但这是OKLCH重要的原因。更大的问题是HSL的核心假设。

HSL的亮度是谎言

HSL相比十六进制确实有实质性的改进。色相、饱和度、亮度——概念上合理,人类可编辑。问题在于,“L”并不像你想象的那样意味着亮度。

将黄色置于 hsl(60, 100%, 50%) ,将蓝色置于 hsl(240, 100%, 50%) 并并列。两者都恰好处于50%的亮度。

.yellow { background: hsl(60, 100%, 50%); }
.blue   { background: hsl(240, 100%, 50%); }

黄色看起来几乎像白色,蓝色看起来是中等偏暗。它们的亮度感知完全不同。这是HSL的感知非均匀性——L轴并不对应人类视觉对亮度的处理方式。

这在构建颜色尺度时会产生真实维护问题。如果你通过在HSL中逐步增加L值来生成一个9级的色阶,你的黄色和青色会显得过曝,而蓝色和紫色则显得浑浊。你最终不得不手动调整数值,这完全违背了系统化方法的初衷。

OKLCH:专为感知设计

OKLCH由Björn Ottosson于2020年设计。它基于1970年代的CIELAB(一种感知色域空间),但修正了其已知的色相偏移问题——特别是紫色/蓝色问题,即调整色度时会明显改变感知色相。

三个通道:

  • L(亮度) ——从0到1,感知上均匀。黄色中L为0.5的亮度与蓝色中L为0.5的亮度实际相同。
  • C(色度) ——从0(灰色)开始,增加到大约0.3-0.4,对应高度饱和的颜色。没有固定上限——上限随色相和目标色域而变化。
  • H(色相) ——从0到360度,大致相当于HSL的色相。

以下是Tailwind蓝色500在两种系统中的表现:

/* sRGB hex */
background: #3b82f6;

/* OKLCH equivalent — same color, different notation */
background: oklch(0.623 0.214 259.1);

/* Push chroma past sRGB — more vivid blue on P3 displays, clips gracefully on sRGB */
background: oklch(0.623 0.27 259.1);

最后一个值超出了sRGB色域。在支持P3的浏览器中,会渲染更鲜艳的版本;较旧的浏览器则会裁剪到最接近的sRGB等效值。实现渐进式增强,无需额外努力。

color-mix() 和为什么色域会影响混合效果

color-mix() 在Chrome 111、Firefox 113和Safari 16.2中推出。它按比例混合两种颜色——简单明了。但你指定的色域会显著影响结果。

/* Mixes through sRGB — midpoint is a washed-out brown-grey */
background: color-mix(in srgb, oklch(0.7 0.2 30), oklch(0.7 0.2 270));

/* Mixes through the OKLCH color wheel — midpoint is a vivid purple */
background: color-mix(in oklch, oklch(0.7 0.2 30), oklch(0.7 0.2 270));

当你在sRGB中混合橙色和蓝色时,你是在平均原始通道值。中间点会经过一种去饱和的棕灰色。而在OKLCH中,你是在色轮上进行插值——你最终会落在一个鲜艳的紫色上。哪种结果正确取决于意图,但对于UI过渡、渐变和悬停状态,OKLCH的插值几乎总是你想要的结果。

一个实际用例:无需硬编码第二个十六进制值即可生成禁用状态。

.button--disabled {
  background: color-mix(in oklch, var(--color-primary) 40%, white);
  cursor: not-allowed;
}

相对颜色语法

相对颜色语法(Chrome 119+、Firefox 128+、Safari 16.4+)允许你通过修改现有颜色的各个通道来推导出新颜色:

:root {
  --brand: oklch(0.623 0.214 259.1);
}

.button:hover {
  /* Lighten by 8% lightness units */
  background: oklch(from var(--brand) calc(l + 0.08) c h);
}

.button:active {
  /* Darken and reduce chroma slightly */
  background: oklch(from var(--brand) calc(l - 0.08) calc(c - 0.02) h);
}

.button--muted {
  /* Drop chroma to near-zero: perceptual grey at the same lightness */
  background: oklch(from var(--brand) l 0.03 h);
}

这取代了Sass的 lighten(), darken(),并且 desaturate() ,使用原生CSS——无需预处理器,无需构建步骤,无需同步多个十六进制值。而且由于你使用的是OKLCH,“变亮”在你色板中的每个色相上都会真正显得更亮,而不仅仅是在部分色相上。

一个真正的局限性:复杂的通道约束(如限制色度以保持在色域内)需要冗长的 calc() 链,这些链会迅速变得复杂。对于简单的亮度和色度调整,语法简洁明了。对于更复杂的情况,预先计算值并生成CSS自定义属性更为可维护。

2026年的浏览器支持

特征铬合金FirefoxSafari
oklch()111+113+15.4+
color-mix()111+113+16.2+
相对颜色语法119+128+16.4+
color(display-p3)111+113+10+

oklch() 的全球支持在2026年中已超过90%。少数支持者是较旧的基于Chromium的企业浏览器以及仍在运行Firefox 113以下版本的系统。如果这些浏览器在你的用户群体中存在,只需两行备用代码即可。

.button {
  background: #3b82f6; /* sRGB fallback */
}

@supports (background: oklch(0 0 0)) {
  .button {
    background: oklch(0.623 0.214 259.1);
  }
}

在实际应用中:如果你的分析确认Chrome 111+、Firefox 113+和Safari 15.4+,你可以完全跳过备用代码。该 @supports 包装器是为了在内部工具中提供安心,而你无法控制浏览器版本。

转换你现有的配色方案

OKLCH采用过程中的主要障碍是从你现有的十六进制值转换为OKLCH坐标,并理解每个颜色的通道含义。该 统一色彩空间转换器 可双向转换——粘贴一个十六进制或HSL值,得到OKLCH输出,然后从真实参考点开始调整L和C。它支持HSL、RGB、Lab、LCH、HSV和OKLCH,当你从Figma文件获取十六进制值并需要转换为可理解的OKLCH值时,这一点非常有用。

如何实际迁移

你不必一次性重写所有内容。一个实用的步骤序列:

  1. 从交互式颜色开始 ——你的主要、次要和破坏性令牌。这些是你已经为悬停、激活和禁用状态生成变体的颜色。OKLCH与相对颜色语法立即用原生CSS替代了这些逻辑。
  2. 暂时保留静态颜色使用十六进制 ——文本、背景、边框。这些颜色不会被程序化操作,因此目前转换它们并无收益。
  3. 从零开始构建下一个新系统,使用OKLCH ——这才是感知均匀性带来的结构性优势。你的中性色阶的500级将真正处于视觉中间点,而所有色相的饱和色将保持一致,无需手动调整。

目标不是为了OKLCH本身。而是拥有一个数学模型与人眼所见一致的颜色系统——这样你不再每次需要稍微更浅的蓝色时都需手动补偿。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?