CSS color-mix函数完全指南:不用JS也能调色
以前做颜色变体要写很多代码,现在CSS原生支持color-mix,让你直接在样式表里混合颜色。主题色、悬浮色、半透明效果,一行代码就能搞定。
你以前是怎么做颜色变体的
做一套按钮组件,需要hover色、禁用色、浅色背景,以前的写法是这样的:
.btn {
background: #3b82f6;
}
.btn:hover {
background: #2563eb;
}
.btn:disabled {
background: #93c5fd;
}或者用SCSS的darken和lighten函数,但那些需要构建工具。
现在原生CSS有了color-mix,不用那么麻烦了。
基础语法
color-mix(in <颜色空间>, 颜色A <百分比>, 颜色B <百分比>)颜色空间有srgb、hsl、oklch、lab等。推荐用oklch,这种颜色空间感知比较均匀,混出来的效果最自然。
百分比是指颜色A占多少比例,颜色B占剩下的。两个百分比加起来不需要等于100%。
/* 蓝色和白色各一半,得到浅蓝色 */
color: color-mix(in srgb, #3b82f6 50%, white);
/* 蓝色加30%黑色,得到深蓝色 */
color: color-mix(in srgb, #3b82f6, black 30%);
/* 蓝色加透明,得到半透明效果 */
background: color-mix(in srgb, #3b82f6 60%, transparent);浏览器兼容性
| 浏览器 | 支持版本 | 发布时间 |
|---|---|---|
| Chrome | 111+ | 2023年3月 |
| Firefox | 113+ | 2023年5月 |
| Safari | 16.2+ | 2022年12月 |
| Edge | 111+ | 2023年3月 |
2023年底开始可以放心在生产环境使用,全球覆盖率超过90%。
实战1:用CSS变量做主题色系
只定义一个主色,自动生成深色、浅色、半透明版本:
:root {
--primary: #3b82f6;
/* 自动生成色系,不用手动调色了 */
--primary-dark: color-mix(in oklch, var(--primary), black 20%);
--primary-darker: color-mix(in oklch, var(--primary), black 40%);
--primary-light: color-mix(in oklch, var(--primary), white 40%);
--primary-lighter: color-mix(in oklch, var(--primary), white 70%);
--primary-alpha-20: color-mix(in srgb, var(--primary) 20%, transparent);
--primary-alpha-10: color-mix(in srgb, var(--primary) 10%, transparent);
}
.btn {
background: var(--primary);
color: white;
}
.btn:hover {
background: var(--primary-dark);
}
.btn:active {
background: var(--primary-darker);
}
.btn:disabled {
background: var(--primary-lighter);
color: var(--primary-light);
cursor: not-allowed;
}
.btn-ghost {
background: var(--primary-alpha-10);
color: var(--primary);
border: 1px solid var(--primary-alpha-20);
}
.btn-ghost:hover {
background: var(--primary-alpha-20);
}换主题色只需要改--primary这一个变量,整套色系都会跟着变。
实战2:动态悬浮色
不用再硬编码每个颜色的hover效果了:
/* 任意颜色的卡片,hover时自动加深 */
.card {
--card-color: #10b981;
background: var(--card-color);
transition: background 0.2s;
}
.card:hover {
background: color-mix(in oklch, var(--card-color), black 15%);
}
/* 多彩标签,hover色自动计算 */
.tag {
--tag-bg: #f59e0b;
background: color-mix(in srgb, var(--tag-bg) 15%, transparent);
color: color-mix(in oklch, var(--tag-bg), black 30%);
border: 1px solid color-mix(in srgb, var(--tag-bg) 40%, transparent);
}
.tag:hover {
background: color-mix(in srgb, var(--tag-bg) 25%, transparent);
}实战3:暗色模式颜色适配
:root {
--bg: white;
--text: #1f2937;
--border: #e5e7eb;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #111827;
--text: #f9fafb;
--border: #374151;
}
}
.card {
background: var(--bg);
color: var(--text);
border: 1px solid var(--border);
}
/* 暗色模式下卡片头部自动用半透明白色叠加 */
.card .card-header {
background: color-mix(in srgb, var(--text) 5%, transparent);
}
.card:hover {
/* 亮色模式变深,暗色模式变浅,同一行代码两个效果都正确 */
background: color-mix(in srgb, var(--bg), var(--text) 5%);
}实战4:渐变色中间色计算
需要手写渐变但不知道中间色是什么,color-mix可以直接算出来:
.gradient-banner {
--start: #6366f1;
--end: #ec4899;
/* 手动计算中间色 */
--mid: color-mix(in oklch, var(--start) 50%, var(--end));
background: linear-gradient(
135deg,
var(--start) 0%,
var(--mid) 50%,
var(--end) 100%
);
}
/* 更细腻的5步渐变 */
.gradient-5 {
--c1: #3b82f6;
--c2: #8b5cf6;
background: linear-gradient(
to right,
var(--c1),
color-mix(in oklch, var(--c1) 75%, var(--c2)),
color-mix(in oklch, var(--c1) 50%, var(--c2)),
color-mix(in oklch, var(--c1) 25%, var(--c2)),
var(--c2)
);
}完整可运行Demo
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>color-mix函数演示</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: sans-serif; background: #f8fafc; padding: 32px; }
/* 动态主题色系 */
.theme-demo {
--primary: #6366f1;
--primary-dark: color-mix(in oklch, var(--primary), black 20%);
--primary-light: color-mix(in oklch, var(--primary), white 50%);
--primary-lighter: color-mix(in oklch, var(--primary), white 80%);
--primary-alpha: color-mix(in srgb, var(--primary) 15%, transparent);
display: flex;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 24px;
}
.swatch {
width: 80px;
height: 80px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
color: white;
}
.s1 { background: var(--primary-dark); color: white; }
.s2 { background: var(--primary); color: white; }
.s3 { background: var(--primary-light); color: white; }
.s4 { background: var(--primary-lighter); color: var(--primary-dark); }
.s5 { background: var(--primary-alpha); color: var(--primary-dark); border: 1px solid var(--primary-light); }
/* 按钮演示 */
.btn-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
.btn {
--c: #3b82f6;
padding: 10px 20px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: background 0.15s, transform 0.1s;
}
.btn.solid {
background: var(--c);
color: white;
}
.btn.solid:hover {
background: color-mix(in oklch, var(--c), black 18%);
}
.btn.solid:active {
transform: scale(0.97);
}
.btn.ghost {
background: color-mix(in srgb, var(--c) 12%, transparent);
color: var(--c);
border: 1.5px solid color-mix(in srgb, var(--c) 35%, transparent);
}
.btn.ghost:hover {
background: color-mix(in srgb, var(--c) 22%, transparent);
}
.btn.green { --c: #10b981; }
.btn.red { --c: #ef4444; }
/* 渐变演示 */
.gradient-bar {
--c1: #3b82f6;
--c2: #ec4899;
height: 48px;
border-radius: 10px;
background: linear-gradient(
to right,
var(--c1),
color-mix(in oklch, var(--c1) 75%, var(--c2)),
color-mix(in oklch, var(--c1) 50%, var(--c2)),
color-mix(in oklch, var(--c1) 25%, var(--c2)),
var(--c2)
);
}
h3 { margin-bottom: 12px; color: #374151; font-size: 14px; }
</style>
</head>
<body>
<h3>主题色系(只有一个主色变量)</h3>
<div class="theme-demo">
<div class="swatch s1">深色</div>
<div class="swatch s2">主色</div>
<div class="swatch s3">浅色</div>
<div class="swatch s4">更浅</div>
<div class="swatch s5">半透明</div>
</div>
<h3>按钮悬浮色自动计算</h3>
<div class="btn-row">
<button class="btn solid">蓝色按钮</button>
<button class="btn solid green">绿色按钮</button>
<button class="btn solid red">红色按钮</button>
<button class="btn ghost">Ghost按钮</button>
<button class="btn ghost green">Ghost绿</button>
</div>
<h3>color-mix计算渐变中间色</h3>
<div class="gradient-bar"></div>
</body>
</html>选哪个颜色空间
| 颜色空间 | 特点 | 推荐用途 |
|---|---|---|
| srgb | 传统RGB混色,速度快 | 透明度变体(加transparent) |
| hsl | 色相饱和度亮度,直观 | 色轮旋转、互补色 |
| oklch | 感知均匀,亮度一致 | 主题色深浅变体,首选 |
| lab | 科学级感知均匀 | 精确色差计算 |
经验法则:加深加浅用oklch,加透明用srgb。
总结
| 场景 | 以前的做法 | 现在的做法 |
|---|---|---|
| 生成hover颜色 | 手动挑色或用SCSS的darken函数 | color-mix(in oklch, var(--c), black 15%) |
| 生成半透明色 | rgba(59, 130, 246, 0.2) | color-mix(in srgb, #3b82f6 20%, transparent) |
| 多彩组件色系 | 每个颜色写4到5个变量 | 一个主色变量,其余自动推导 |
| 渐变中间色 | 凭感觉猜 | color-mix精确计算 |
color-mix是目前CSS原生颜色操作中最实用的函数。配合CSS变量一起用,设计系统的实现会优雅很多。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!