CSS Color 函数与色彩空间:从 hex 到现代色彩体系

信息图

CSS 是流动的韵律,JS 是叙事的节奏。

一、hex 之外的世界

CSS 迎来了 oklch()oklab()display-p3 等全新的色彩函数和色域。

这些新函数不只是语法糖,它们解决了传统色彩模型的一些根本性问题:HSL 的亮度感知不均匀,sRGB 色域覆盖范围有限。

二、从 HSL 到 OKLCH:更直觉的色彩模型

HSL(色相、饱和度、亮度)虽然比 RGB 更直观,但它有一个严重问题——亮度感知不线性。比如,同样是 50% 亮度,黄色的视觉亮度比蓝色高得多:

/* HSL 的亮度问题:看似相同亮度,视觉感受不同 */
.hsl-yellow {
  background: hsl(60, 100%, 50%); /* 视觉上很亮 */
}

.hsl-blue {
  background: hsl(240, 100%, 50%); /* 视觉上很暗 */
}

/* OKLCH:感知均匀的色彩空间 */
.oklch-yellow {
  background: oklch(0.8, 0.15, 100); /* 亮度值 0.8 */
}

.oklch-blue {
  background: oklch(0.8, 0.15, 260); /* 同样是亮度 0.8 */
}

OKLCH 的三个参数分别是:

  • L(亮度):0 到 1 之间,感知均匀的亮度值
  • C(色度):颜色的饱和度/鲜艳程度
  • H(色相):0 到 360 度的色相角度
/* 使用 OKLCH 构建色彩系统 */
:root {
  --primary: oklch(0.55, 0.2, 260);    /* 沉稳的蓝色 */
  --primary-light: oklch(0.7, 0.15, 260);  /* 浅蓝色 */
  --primary-dark: oklch(0.35, 0.25, 260);  /* 深蓝色 */
  
  --success: oklch(0.6, 0.2, 145);      /* 健康的绿色 */
  --warning: oklch(0.7, 0.2, 85);       /* 温暖的黄色 */
  --danger: oklch(0.55, 0.25, 30);      /* 警示的红色 */
}

/* 通过调整色度创建灰色系 */
:root {
  --gray-100: oklch(0.97, 0, 0);
  --gray-200: oklch(0.92, 0, 0);
  --gray-300: oklch(0.85, 0, 0);
  --gray-500: oklch(0.6, 0, 0);
  --gray-700: oklch(0.35, 0, 0);
  --gray-900: oklch(0.15, 0, 0);
}

三、相对颜色语法:从现有颜色派生新颜色

CSS Color Level 4 引入的相对颜色语法,让我们可以基于一个现有颜色轻松创建变体:

:root {
  --brand: #3498db;
}

.button {
  background: var(--brand);
  color: white;
  border: 2px solid var(--brand);
}

/* 使用相对颜色语法创建 hover 状态 */
.button:hover {
  /* 将 --brand 的亮度降低 20% */
  background: rgb(from var(--brand) r calc(g * 0.8) calc(b * 0.8));
}

.button--secondary {
  /* 将 --brand 的不透明度设为 10% 作为背景 */
  background: rgb(from var(--brand) r g b / 0.1);
  color: var(--brand);
  border: 2px solid var(--brand);
}
/* 在 HSL 中更直观的相对颜色 */
.alert {
  --hue: 0; /* 红色 */
  background: hsl(from var(--hue) h s l / 0.1);
  border: 1px solid hsl(from var(--hue) h s l);
  color: hsl(from var(--hue) h calc(s * 0.8) calc(l * 0.6));
}

.alert--success {
  --hue: 145; /* 绿色 */
}

.alert--warning {
  --hue: 55; /* 黄色 */
}

四、P3 色域:让屏幕色彩更丰富

传统 Web 颜色被限制在 sRGB 色域中,而现代显示器(尤其是 Apple 的 Retina 和 Pro Display XDR)支持更广的 Display P3 色域:

/* sRGB 色域:传统 Web 标准 */
.card {
  background: color(srgb 0.2 0.5 0.9);
}

/* Display P3 色域:更鲜艳的色彩 */
@supports (color: color(display-p3 1 1 1)) {
  .card {
    background: color(display-p3 0.2 0.52 0.95);
  }
}

/* 使用媒体查询检测色域 */
@media (color-gamut: p3) {
  .gradient-hero {
    background: linear-gradient(
      135deg,
      color(display-p3 0.95 0.2 0.3),
      color(display-p3 0.3 0.4 0.95)
    );
  }
}

/* 回退方案 */
.gradient-hero {
  background: linear-gradient(135deg, #e74c3c, #3498db);
}

P3 色域大约比 sRGB 多 25% 的色彩空间,尤其在红色和绿色区域更加丰富。

五、color-mix:混合颜色的利器

color-mix() 函数让我们可以在 CSS 中直接混合两种颜色,无需预处理器的帮助:

/* 基础颜色混合 */
.mixed-bg {
  /* 50% 蓝色 + 50% 红色 = 紫色 */
  background: color-mix(in srgb, #3498db, #e74c3c);
}

/* 指定混合比例 */
.button-primary {
  background: color-mix(in srgb, var(--primary) 80%, black);
}

.button-primary:hover {
  background: color-mix(in srgb, var(--primary) 60%, black);
}

/* 在不同的色彩空间中混合 */
.oklch-mix {
  /* 在 OKLCH 色彩空间中混合,结果更自然 */
  background: color-mix(in oklch, var(--primary), var(--secondary));
}

.hsl-mix {
  /* 在 HSL 色彩空间中混合 */
  background: color-mix(in hsl, var(--primary), var(--secondary));
}

/* 实战:主题色变体 */
.card {
  --card-bg: color-mix(in oklch, var(--surface), white 80%);
  --card-border: color-mix(in oklch, var(--surface), black 90%);
  
  background: var(--card-bg);
  border: 1px solid var(--card-border);
}

/* 文字颜色对比度 */
.dynamic-text {
  /* 在深色背景上使用浅色文字 */
  --bg: #1a1a2e;
  --text: color-mix(in oklch, var(--bg), white 80%);
  background: var(--bg);
  color: var(--text);
}

六、对比色与可访问性

现代 CSS 颜色函数让可访问性设计变得更加容易:

/* 自动计算对比色 */
.accessible-button {
  --bg: #3498db;
  --text: oklch(from var(--bg) calc(1 - l) 0.05 h);
  background: var(--bg);
  color: var(--text);
}

/* 使用 contrast-color(未来的特性) */
/* .future-button {
  background: var(--bg);
  color: contrast-color(var(--bg));
} */

/* 确保 WCAG AA 标准 */
:root {
  --text-color: oklch(0.15, 0, 0);
  --bg-color: oklch(0.95, 0, 0);
  /* 对比度约为 15:1,远超 AA 标准的 4.5:1 */
}

[data-theme="dark"] {
  --text-color: oklch(0.85, 0, 0);
  --bg-color: oklch(0.2, 0, 0);
  /* 对比度约为 11:1,符合 AA 标准 */
}
graph TD
    A[CSS样式层] --> B[变量定义]
    A --> C[布局系统]
    A --> D[动画效果]
    B --> E[主题色彩]
    B --> F[间距系统]
    C --> G[Flexbox]
    C --> H[Grid]

七、结语:色彩是沟通的语言

#fffoklch(0.95, 0, 0),CSS 色彩系统的进化不仅仅是语法变化,更是我们对色彩理解的深化。更好的色彩模型意味着我们可以更精确地控制用户的情感体验。

作为一个从美术学院转行的前端,我特别喜欢 OKLCH 的色彩模型——它让我可以用"亮度、色度、色相"这种贴近设计师思维的方式来描述颜色,而不是用机器友好的 RGB。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐