跳到主要内容
轻盈的鱼

← 返回归档

浏览器颜色格式指南:为什么整站换肤首选 OKLCH

日期:分类:cssguide标签:OKLCHCSS样式主题色color-mix

CSS 能写颜色的方式很多,但真正适合「改一个值,整站风格跟着走」的并不多。本文先扫一遍浏览器支持的颜色格式,再重点讲 OKLCH 的优缺点,以及用 oklch + --hue 做整站主题色的实现方案(本站 blog 主题就是这套思路)。

浏览器支持的颜色格式一览

按成熟度与能力,大致可以分成三层。

1. 经典 sRGB(几乎无处不支持)

  • 命名色:redtransparentcurrentColor
  • Hex:#f00 / #ff0000 / #ff000080
  • rgb() / rgba():现代写法可 rgb(255 0 0 / 50%)
  • hsl() / hsla():按色相/饱和度/明度调色,直觉强但感知不均
  • hwb():Hue + Whiteness + Blackness,适合「掺白掺黑」

2. 感知均匀 / 广色域(2023 起主流可用)

  • oklch() / oklab():Chrome 111+、Firefox 113+、Safari 15.4+
  • lab() / lch():CIE Lab/LCH,同代支持
  • color():指定色域,如 color(display-p3 1 0 0)
  • color-mix():在指定色彩空间里混色(建议 in oklch

3. 相对颜色(Relative Color,稍晚成熟)

形如 oklch(from var(--brand) calc(l + 0.1) c h)。Chrome/Edge 131+、Firefox 133+、Safari 18+ 支持较完整。很适合从基色派生 hover/浅色,但整站主色仍更稳妥地用「CSS 变量 + oklch」显式声明。

OKLCH 是什么

OKLCH 是 OKLab 的圆柱坐标写法,三个通道职责清晰:

  • L(Lightness):感知明度,约 0–1(也可用百分比)
  • C(Chroma):彩度,大约 0–0.4 常见可用区间
  • H(Hue):色相角度 0–360
1/* L C H [/ alpha] */
2color: oklch(0.55 0.14 250);
3color: oklch(0.55 0.14 250 / 80%);
4
5/* 色相交给变量,是整站换肤的关键 */
6--hue: 250;
7--accent: oklch(0.5 0.15 var(--hue));

OKLCH 的优点

  1. 感知均匀:同样改 ΔL,不同色相看起来「变亮/变暗」更接近一致;HSL 的 L 做不到这点。
  2. 通道可拆:只动 H 换品牌色,只动 L 做暗色模式,只动 C 控制鲜艳度——整站主题系统非常吃这套模型。
  3. 可表达广色域:在支持 Display P3 的屏幕上,能比 hex/rgb 更鲜艳;超出 sRGB 时浏览器会合理映射。
  4. 与 color-mix / relative color 搭配好:混色、派生 hover、半透明叠层时,结果更「像人眼预期」。
  5. 浏览器支持已够用:到 2026 年,基础 oklch() 对多数站点可直接作为默认,不必再当 progressive enhancement。

OKLCH 的缺点与坑

  1. 色域裁剪:高彩度 C 在某些色相会超出显示色域,浏览器会 gamut map,可能「看起来没那么艳」。设计时别盲目拉高 C。
  2. 与 HSL 色相不完全同轴:同样写 250,OKLCH 与 HSL 视觉色相会有偏差。从旧 HSL 主题迁移时,别假设数字可直接平移。
  3. 设计工具链路仍在补齐:Figma 等对 OKLCH 支持不如 hex 成熟,团队协作常要转换。
  4. 极旧浏览器会整条忽略:若仍要照顾很老的内核,需先写 sRGB fallback,再写 oklch。
  5. Canvas / 第三方库未必原生理解:WebGL、部分图表库仍要 RGB;需要在 JS 侧转换(可用 culori 等)。

整站风格修改:推荐实现方案

核心思路只有一句话:把色相抽成单一 token --hue,其余颜色用 oklch(L C var(--hue)) 或 calc(var(--hue) + 偏移) 派生。

步骤 1:定义色相 token 与语义色板

1html.blog-skin {
2 --hue: 250;
3
4 /* 背景:高 L、极低 C,仍带一点主题色气 */
5 --page-bg: oklch(0.98 0.008 var(--hue));
6 --card-bg: oklch(1 0.004 var(--hue));
7 --card-border: oklch(0.92 0.02 var(--hue));
8
9 /* 文字:中低 L,弱彩度,避免「发灰」或「发脏」 */
10 --text: oklch(0.28 0.02 var(--hue));
11 --text-muted: oklch(0.45 0.03 var(--hue));
12
13 /* 强调色:固定 L/C,只换 H */
14 --accent: oklch(0.5 0.15 var(--hue));
15 --accent-2: oklch(0.55 0.14 calc(var(--hue) + 30));
16 --accent-3: oklch(0.55 0.14 calc(var(--hue) + 60));
17}

组件里尽量只用语义变量(--accent--text),不要散落硬编码 hex。这样改风格 = 改 token,而不是满仓库搜色值。

步骤 2:暗色模式只改 L(和少量 C)

1html.blog-skin.dark {
2 --page-bg: oklch(0.14 0.015 var(--hue));
3 --card-bg: oklch(0.18 0.02 var(--hue));
4 --card-border: oklch(0.28 0.02 var(--hue));
5 --text: oklch(0.95 0.01 var(--hue));
6 --text-muted: oklch(0.7 0.02 var(--hue));
7 /* 暗色下强调色略提亮、略降彩,避免刺眼 */
8 --accent: oklch(0.72 0.12 var(--hue));
9}

色相继续共用 --hue,亮暗切换不会把品牌色「拧歪」。

步骤 3:运行时改 --hue 即可换肤

1const DEFAULT_HUE = 250
2const HUE_KEY = 'themeHue'
3
4function applyHue(value) {
5 const n = Math.max(0, Math.min(360, Math.round(Number(value))))
6 document.documentElement.style.setProperty('--hue', String(n))
7 localStorage.setItem(HUE_KEY, String(n))
8}
9
10// 页面加载恢复用户偏好
11const saved = localStorage.getItem(HUE_KEY)
12if (saved != null) applyHue(saved)
13
14// UI:滑块 / 色板只改这一个数
15// applyHue(180) → 整站背景、边框、强调色、标签色一起偏移

本站 header 的「主题色」面板就是这样做的:写 --hue,CSS 里所有 oklch(... var(--hue)) 自动重算,无需重渲染组件树。

步骤 4:用色相偏移做「同族多彩」

标签、语法高亮、装饰渐变不需要第二套主题系统,只要在主色相上加固定偏移:

1.chroma-tag--0 { color: oklch(0.48 0.15 calc(var(--hue) + 0)); }
2.chroma-tag--1 { color: oklch(0.48 0.15 calc(var(--hue) + 55)); }
3.chroma-tag--2 { color: oklch(0.48 0.15 calc(var(--hue) + 110)); }
4
5--prose-hr-gradient: linear-gradient(
6 90deg,
7 oklch(0.48 0.15 calc(var(--hue) + 0)),
8 oklch(0.48 0.15 calc(var(--hue) + 110)),
9 oklch(0.48 0.15 calc(var(--hue) + 220))
10);

步骤 5:半透明与叠色用 color-mix(in oklch, …)

1--accent-soft: color-mix(in oklch, var(--accent) 22%, transparent);
2--accent-shadow: color-mix(in oklch, var(--accent) 30%, transparent);
3
4/* 需要透出底图时,再把不透明 base 混一点透明 */
5--header-bg: color-mix(in oklch, var(--header-bg-base) 85%, transparent);

步骤 6:可选 fallback(仅当要照顾极旧浏览器)

1.button {
2 background: #5b4fcf; /* sRGB fallback */
3 background: oklch(0.5 0.15 270);
4}
5
6@supports (color: oklch(0 0 0)) {
7 .button {
8 background: oklch(0.5 0.15 var(--hue));
9 }
10}

为什么不优先用 HSL 做整站主题

HSL 也能 hsl(var(--hue) 70% 45%),写法更熟。问题在于:相同「明度百分比」在黄/蓝上视觉权重差很大——换肤时有的色相显得过亮刺眼,有的又发闷。OKLCH 的 L 更接近人眼,一套 L/C 表跨色相更稳,维护成本更低。

选型速查

  • 整站主题 / 换肤:oklch + --hue(首选)
  • 半透明、叠色、hover:color-mix(in oklch, …)
  • 指定 P3 等色域:color(display-p3 …)
  • 从已有色派生通道:relative color(注意浏览器版本)
  • 对外素材 / 邮件 / 极旧兼容:hex / rgb 作 fallback

小结

浏览器颜色格式已经从「只能写 hex/rgb」走到「感知均匀 + 广色域 + 混色」的新常态。若目标是改整站风格,OKLCH 是目前最均衡的选择:L/C/H 可独立控制,配合单一 --hue 就能完成亮暗模式、强调色、多彩标签与运行时换肤。代价是需要习惯新数字空间,并留意高彩度裁剪与工具链转换——但对现代站点来说,这点成本通常值得。

想直观感受效果:打开本站 header 的主题色滑块,拖动色相,看背景、按钮、标签与代码高亮如何一起偏移。那就是 OKLCH 整站主题方案最有说服力的演示。

版权信息

日期2026/07/31
协议CC BY-NC-SA 4.0 转载请注明出处
评论
  • Admin <334220235@qq.com>·2026/07/31 14:02
    test