color-mix() 更可靠,因它在 lch 等指定色彩空间中线性调控亮度(l 值),结果可预测、可复现,且直接支持 wcag 对比度验证与动态适配,而手调 hex 或 hsl 易偏差、不可控。

color-mix() 为什么比手调 hex 更可靠
人眼对亮度和色相的敏感度不一致,手动改 #ff6b6b 到 #ff4757 看着“更红”,但对比度可能反而掉出 WCAG AA 标准。浏览器原生的 color-mix() 直接在指定色彩空间(比如 lch)里按明度差值混合,结果可预测、可复现。
- 必须指定色彩空间:
color-mix(in lch, red 70%, white 30%)才能控明度;用srgb混合容易过曝或发灰 -
lch空间里,L值直接对应相对亮度(0=黑,100=白),调整它比调hsl()的lightness更线性 - 旧版 Safari 不支持
color-mix(),得用@supports (color: color-mix(in lch, red, blue))包一层降级逻辑
用 relative color syntax 动态提亮文字底色
按钮悬停时背景变深,文字却还用固定 #fff,常导致对比度跌破 4.5:1。用 color(display-p3 0.9 0.9 0.9) 这类写法无法响应背景变化;而 color-mix() + color() 提取当前色,就能真·动态适配。
- 写法示例:
color: color-mix(in lch, currentColor 80%, black 20%)—— 文字始终比当前背景暗 20% L 值 - 不能对
currentColor直接做lighten(),CSS 没这函数;必须走color-mix()或color()转换再混合 - 如果底色是渐变或图片,
currentColor失效,得靠 JS 读取 computedStyle 后注入 CSS 变量,此时color-mix()依然可用,只是源头变了
对比度不足时,lch() 比 hsl() 更快定位问题
WCAG 要求文本与背景的相对亮度比 ≥ 4.5:1,这个比值只跟两个颜色的 L 值有关((L1 + 0.05) / (L2 + 0.05))。用 lch(50% 80 280) 定义颜色,一眼看出 L 是 50;换成 hsl(280 80% 50%),你根本不知道它实际亮度是 22 还是 68。
- 查对比度:浏览器 DevTools 里点开颜色值,选 “LCH” 视图,直接看
L数字,心算两色差值是否够 25+(≈4.5:1) - 别用
hwb()调对比度——它的whiteness和blackness不是线性亮度,混出来容易翻车 - 深色模式下,背景
L常压到 20–30,文字至少要L: 75+,硬套白天的hsl(0 0% 90%)可能只有L: 62
兼容性兜底时,避免用 Sass/lighten() 算错 lch 亮度
Sass 的 lighten($color, 20%) 是在 hsl 空间操作,把 lightness 加 20%,但 hsl(0 100% 30%) 和 hsl(0 100% 50%) 的真实亮度差远小于 lch(30% ...) 和 lch(50% ...)。用它生成的“高对比”方案,实测常卡在 3.8:1。
- 真正兜底方案:用 PostCSS 插件(如
postcss-color-mix)把color-mix()编译成rgb()十六进制,而非靠 Sass 函数模拟 - 如果必须用 Sass,改用
scale-color($color, $lightness: 30%)并手动映射到 lch L 值表,比lighten()略准,但仍有误差 - 所有兜底颜色必须重新用 axe DevTools 或 Contrast Checker 扫一遍,不能信“编译出来了就达标”
真正难的不是写出 color-mix(),而是确认设计系统里每个基础色的 lch() 三元组都标对了——一个 L 值写错 5,整套按钮文字对比度就全线下滑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











