Kodokon kodokon.com

颜色与高级函数:oklch、color-mix、min/max

利用感知均匀的色彩空间、相对颜色语法和带类型的数学函数,构建由浏览器为你计算的设计系统。

10 分钟 · 3 题

在 Kodokon 中打开本课

hsl() 的结构性缺陷在于:它的明度并非感知均匀的。hsl(60 100% 50%)(黄色)看起来耀眼夺目,而 hsl(240 100% 50%)(蓝色)看起来却很暗,尽管两者的 L 相同。oklch 修正了这一点:它的 L 分量(0 到 1)度量的是感知明度,C 是色度(绝对饱和度,0 到大约 0.37),H 是色相角。在 L 不变的情况下改变 H 会保持感知亮度不变:你的调色板变体终于变得可预测。再结合相对颜色语法from),浏览器就能自行推导出你的悬停、柔化或深色变体。

CSS
:root {
  --brand: oklch(0.65 0.19 255);
  --dark: oklch(from var(--brand) calc(l - 0.15) c h);
  --muted: oklch(from var(--brand) l calc(c / 2) h);
  --accent: oklch(from var(--brand) l c calc(h + 180));
}
单一源色,三个计算得出的派生色:l、c、h 通道被暴露为局部变量。

oklch 能够描述超出 sRGB 色域、甚至超出 Display-P3 的颜色。当屏幕无法显示这些颜色时,浏览器会怎么做?不是逐通道的粗暴裁剪:规范规定了一种色域映射,它在保持明度和色相的同时逐步降低色度,直到颜色落入目标色域。你可以用 @media (color-gamut: p3) 显式地针对广色域屏幕。另一个混色工具是 color-mix(),它的第一个参数——插值空间——会实实在在地改变结果:蓝色和黄色以 in srgb 混合会变成灰色,而 in oklch 则会穿过鲜艳的色相。

CSS
.badge {
  background: color-mix(in oklch, crimson 70%, white);
  border-color: color-mix(
    in oklch,
    var(--brand),
    transparent 60%
  );
}
与 transparent 混合能得到一个半透明变体,而无需把颜色以 rgba 的形式重复一遍。

min()max()clamp()带类型的数学函数:它们接受在解析时互不兼容的混合单位(rem + vw),因为解析发生在已知视口后的取用值阶段。clamp(MIN, VAL, MAX) 严格等价于 max(MIN, min(VAL, MAX))——由此带来一个规范后果:若 MIN 超过 MAX,则 MIN 获胜。对于流式排版,请始终在中间值里包含一个 rem 分量:一个没有 remfont-size: clamp(1rem, 2.5vw, 3rem) 会忽略用户的文字缩放,这是一个实实在在的无障碍问题。

CSS
h1 {
  font-size: clamp(1.5rem, 1.1rem + 2vw, 3rem);
}
.sidebar {
  width: min(30%, 20rem);
  padding-left: max(1rem, env(safe-area-inset-left));
}
无障碍的流式排版,以及尊重移动端屏幕刘海的边距。

知识检测

确认你已牢记本课的重点内容。

  1. oklch 相对于 hsl 提供了哪个决定性优势?
    • 书写起来更短的语法
    • 从一个色相到另一个色相都感知均匀的 L 明度
    • 保证停留在 sRGB 色域之内的保障
    • 唯一支持透明度通道的色彩空间
  2. 当一个 oklch 颜色超出屏幕色域时,浏览器会怎么做?
    • 它会忽略该声明并保留之前的颜色
    • 它会应用一种主要降低色度的色域映射
    • 它会独立裁剪每个 RGB 通道,不作任何进一步处理
  3. 在 clamp(MIN, VAL, MAX) 中,如果计算得出的 MIN 值超过了 MAX 会怎样?
    • 声明变得无效并被忽略
    • MAX 获胜并对结果封顶
    • MIN 获胜,因为 clamp 展开为 max(MIN, min(VAL, MAX))