背景色是动态的我算了八年,现在 CSS 自己会挑颜色了——contrast-color() 把无障碍配色彻底原生化了

背景色是动态的我算了八年,现在 CSS 自己会挑颜色了——contrast-color() 把无障碍配色彻底原生化了。

深色主题、用户自定义主题、随机渐变背景——只要背景色是动态的,前端就要面对同一个问题:上面的文字该用什么颜色?黑色还是白色?哪个能通过 WCAG AA?

以前靠 JS 算对比度,现在一行 CSS,浏览器自己会选。

contrast-color() 怎么用

.text {
  color: contrast-color(bg-color);
}

.card {
  background: var(--card-bg); /* 可能是任何颜色 */
  color: contrast-color(var(--card-bg));
}

contrast-color() 接受一个背景色作为参数,返回一个满足 WCAG 对比度要求的文字颜色——黑色或白色,哪个更清晰用哪个。不用再手写 if-else 判断亮度。

配合 OKLCH:动态主题的最佳拍档

OKLCH 是 2026 年最值得迁移的颜色格式,它的 L 通道就是亮度值,天然适合与 contrast-color() 配合:

.card {
  background: oklch(65% 0.15 240); /* 用户自定义背景 */
  color: contrast-color(background); /* 自动选黑或白 */
}

OKLCH 的 l 值直接对应人眼亮度感知——contrast-color() 用它判断哪个对比度更高,比 RGB 算出来的准。

多个候选颜色的情况

contrast-color() 还支持多候选颜色,浏览器会挑对比度最高的那个:

.button {
  background: var(--brand);
  color: contrast-color(
    var(--brand),
    in oklch,
    #fff,
    #000,
    #f5c518
  );
}

这个场景适合品牌色按钮——如果品牌色偏深,用白色文字;如果偏浅,用黑色文字;如果都不够清晰,用黄色备选。

浏览器支持与降级

目前 contrast-color() 需要 Chrome 129+ / Edge 129+ / Safari 18+(Baseline 2026),Firefox 还没支持。降级方案:

.text {
  color: #000; /* 降级:保守用黑色 */
}

@supports (color: contrast-color(#fff)) {
  .text {
    color: contrast-color(var(--bg));
  }
}

渐进增强意味着:浏览器支持就用智能配色,不支持就回退到默认色,保证可读性不挂。

实际落地方案

contrast-color() 和 OKLCH 颜色变量配合起来,是目前最干净的动态配色方案:

:root {
  --bg-primary: oklch(95% 0.01 240);
  --text-primary: contrast-color(var(--bg-primary));
}

[data-theme="dark"] {
  --bg-primary: oklch(20% 0.02 240);
  --text-primary: contrast-color(var(--bg-primary));
}

切换主题只需要改背景色的 L 值,文字颜色自动跟着变,五年来靠 JS 计算的那套逻辑可以全删了。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 13 阅读