工具指南13-在线颜色转换工具
做前端开发,和颜色打交道是家常便饭。设计师给你一个 HEX 值 #3B82F6,你要在 CSS 里用 rgba() 做半透明效果;PM 让你调整按钮颜色的亮度,你得在 HSL 色彩空间里操作才方便。颜色格式之间的来回转换,看似简单,实际容易出错——特别是当你需要在多个格式之间反复跳转的时候。
这篇文章会先梳理主流颜色格式的原理和适用场景,然后介绍如何用在线颜色转换工具提高日常开发效率。
颜色格式:不只是换个写法
很多人觉得 HEX、RGB、HSL 只是同一个颜色的不同写法。从结果看确实如此,但它们背后的设计哲学完全不同,这直接决定了各自的适用场景。
HEX:设计师的通用语言
HEX 格式(如 #3B82F6)本质上是 RGB 的十六进制压缩表示。每两位对应一个通道:3B = 红色 59, 82 = 绿色 130, F6 = 蓝色 246。
/* 6位标准写法 */
color: #3B82F6;
/* 8位写法(含透明度) */
color: #3B82F680; /* 最后两位 0x80 = 128, 128/255 ≈ 50% 透明度 */
/* 3位简写(每位重复) */
color: #F00; /* 等同于 #FF0000 */
HEX 的优势是紧凑,设计稿里到处都是它。但手动调色几乎不可能——你很难直观判断 #3B82F6 比 #2563EB 亮了多少。
RGB / RGBA:机器的原生格式
RGB 直接对应显示器的三原色发光原理。每个通道取值 0-255,组合出约 1677 万种颜色。
/* 标准写法 */
color: rgb(59, 130, 246);
/* 带透明度 */
color: rgba(59, 130, 246, 0.5);
/* CSS Color Level 4 新语法 */
color: rgb(59 130 246 / 50%);
RGB 适合需要精确控制每个通道的场景,比如用 JavaScript 做像素级图像处理:
// Canvas 像素操作:灰度化
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
data[i] = gray; // R
data[i + 1] = gray; // G
data[i + 2] = gray; // B
// data[i + 3] 是 Alpha,保持不变
}
ctx.putImageData(imageData, 0, 0);
但 RGB 对人类不友好。“把这个蓝色调亮一点”——在 RGB 里你得同时调三个通道,而且调整比例还不能乱来,否则色相会偏移。
HSL:人类直觉的颜色模型
HSL 才是真正为人类设计的颜色格式。三个参数分别对应:
- H (Hue):色相,0-360度的色环。0/360 = 红,120 = 绿,240 = 蓝
- S (Saturation):饱和度,0% = 灰色,100% = 纯色
- L (Lightness):亮度,0% = 黑色,50% = 纯色,100% = 白色
/* 标准写法 */
color: hsl(217, 91%, 60%);
/* 带透明度 */
color: hsla(217, 91%, 60%, 0.5);
/* CSS Color Level 4 新语法 */
color: hsl(217 91% 60% / 50%);
HSL 的直觉性体现在日常操作中:
/* 用 HSL 生成同色系的浅色/深色变体 */
:root {
--primary: hsl(217, 91%, 60%);
--primary-light: hsl(217, 91%, 75%); /* 只改亮度 */
--primary-dark: hsl(217, 91%, 45%); /* 只改亮度 */
--primary-muted: hsl(217, 40%, 60%); /* 只改饱和度 */
}
同样的操作在 HEX 或 RGB 里要么靠猜,要么靠计算。这就是为什么现代 CSS 设计系统(如 Tailwind CSS 的调色板)内部基本都用 HSL 来生成色阶。
HWB:CSS 新成员
HWB(Hue-Whiteness-Blackness)是 CSS Color Level 4 引入的格式。逻辑更直觉:在一个色相上,加白变浅,加黑变深。
/* 主流浏览器已支持(Chrome 101+, Firefox 96+, Safari 15+) */
color: hwb(217 10% 10%);
HWB 的兼容性数据来源于 Can I Use。目前覆盖率已超过 90%,生产环境使用时建议提供 HSL 降级方案。
颜色转换的实际痛点
如果只是偶尔查一个颜色值,打开浏览器 DevTools 的取色器就够了。但以下场景会让你真正需要一个专门的转换工具:
场景一:设计系统的色板生成
你拿到设计师给的品牌色 #3B82F6,需要生成从 50 到 950 的完整色阶。基本思路是转成 HSL,固定色相,通过调整亮度生成不同深浅。Tailwind 等成熟设计系统在此基础上还会微调色相和饱和度(比如深色阶段色相会偏移几度,避免看起来发灰),所以最终的 HEX 值不是简单的亮度等差。以下是 Tailwind blue 色阶的参考值:
| 色阶 | 大致 HSL | HEX 值 |
|---|---|---|
| 50 | hsl(214, 100%, 97%) | #EFF6FF |
| 100 | hsl(214, 95%, 93%) | #DBEAFE |
| 200 | hsl(214, 97%, 87%) | #BFDBFE |
| 300 | hsl(214, 94%, 78%) | #93C5FD |
| 500 | hsl(217, 91%, 60%) | #3B82F6 |
| 700 | hsl(224, 76%, 48%) | #1D4ED8 |
| 900 | hsl(224, 64%, 33%) | #1E3A8A |
可以看到色相从 214 到 224 有几度偏移,饱和度也不完全一致。这些微调让色阶在视觉上更自然。无论如何,这个过程都需要在 HSL 和 HEX 之间反复转换,没有工具辅助不太现实。
场景二:暗色模式适配
暗色模式不是简单地反转颜色。通常的做法是:
- 把亮色模式的颜色转为 HSL
- 调整亮度(浅色变深,深色变浅)
- 适当降低饱和度(暗底上高饱和色会刺眼)
- 转回 HEX 或 RGB 写入代码
/* 亮色模式 */
:root {
--bg: hsl(0, 0%, 100%);
--text: hsl(217, 33%, 17%);
--accent: hsl(217, 91%, 60%);
}
/* 暗色模式:调亮度 + 降饱和度 */
[data-theme="dark"] {
--bg: hsl(222, 47%, 11%);
--text: hsl(213, 31%, 91%);
--accent: hsl(217, 78%, 65%); /* 饱和度从91%降到78%,亮度从60%提到65% */
}
场景三:无障碍对比度检查
WCAG 2.1 要求正文文本与背景的对比度至少 4.5:1(AA 级别),大号文本至少 3:1。对比度计算需要 RGB 值:
// 相对亮度计算(基于 WCAG 标准)
function relativeLuminance(r, g, b) {
const [rs, gs, bs] = [r, g, b].map(c => {
c = c / 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
});
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}
// 对比度计算
function contrastRatio(rgb1, rgb2) {
const l1 = relativeLuminance(...rgb1);
const l2 = relativeLuminance(...rgb2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
设计师给的是 HEX,WCAG 公式需要 RGB,你的 CSS 变量用的是 HSL。三种格式来回跳,没有工具辅助会很痛苦。
在线颜色转换工具实操
AnyFreeTools 的颜色转换工具覆盖了上面说的这些场景。输入任意格式的颜色值,实时转换为 HEX、RGB、HSL 等格式。
几个典型用法:
快速格式转换:在输入框填入 #3B82F6,立刻得到 rgb(59, 130, 246) 和 hsl(217, 91%, 60%) 等所有格式的对应值,一键复制到代码里。
可视化调色:通过色板或滑块直接选色,比盲猜 HEX 值高效得多。特别是需要微调颜色时,拖动 HSL 的亮度滑块比手动改十六进制字符直观太多。
透明度处理:RGBA 和 HSLA 的透明度在设计到开发的交接中经常出问题。工具能同时显示带透明度和不带透明度的值,减少沟通成本。
所有计算在浏览器本地完成,颜色数据不会上传到服务器。这对处理未发布设计稿的配色方案时尤其重要。
颜色格式转换的底层原理
如果你对转换算法感兴趣,以下是核心逻辑(这也是大多数在线工具背后的实现):
HEX 转 RGB
最简单的转换,纯粹的进制转换:
function hexToRgb(hex: string): [number, number, number] {
const h = hex.replace('#', '');
// 处理3位简写
const full = h.length === 3
? h.split('').map(c => c + c).join('')
: h;
return [
parseInt(full.slice(0, 2), 16),
parseInt(full.slice(2, 4), 16),
parseInt(full.slice(4, 6), 16),
];
}
RGB 转 HSL
这个转换涉及色彩空间映射,稍微复杂一些:
function rgbToHsl(r: number, g: number, b: number): [number, number, number] {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
if (max === min) return [0, 0, l * 100];
const d = max - min;
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
let h = 0;
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
else if (max === g) h = ((b - r) / d + 2) / 6;
else h = ((r - g) / d + 4) / 6;
return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
}
算法的核心是找到 RGB 三通道的最大值和最小值。色相由最大通道决定(红/绿/蓝对应不同的计算公式),饱和度由最大值与最小值的差决定,亮度是最大值与最小值的平均值。
这段代码可以直接在浏览器里运行。注意 Math.round 会损失精度,如果需要链式转换(RGB → HSL → RGB),生产环境建议保留更多小数位再做最终取整。如果你在做组件库或设计系统,把这两个函数封装进工具函数是值得的。
实际开发中的选择建议
不同场景适合不同的颜色格式:
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| 设计稿标注 | HEX | 紧凑,设计工具通用 |
| CSS 变量 / 主题系统 | HSL | 方便生成色阶和变体 |
| Canvas / WebGL | RGB | 与底层 API 对应 |
| 需要透明度 | RGBA 或 HSLA | 显式表达 Alpha 通道 |
| 对比度计算 | RGB | WCAG 公式基于 RGB |
| 打印 / 印刷 | CMYK | 与印刷色域匹配 |
一个常见的实践是:设计系统的源头用 HSL 定义颜色变量,在需要的地方转成其他格式。CSS 自定义属性可以这样组织:
:root {
/* 源头:HSL 分离变量,方便动态调整 */
--blue-h: 217;
--blue-s: 91%;
--blue-l: 60%;
/* 组合使用 */
--blue-500: hsl(var(--blue-h), var(--blue-s), var(--blue-l));
--blue-400: hsl(var(--blue-h), var(--blue-s), 68%);
--blue-600: hsl(var(--blue-h), var(--blue-s), 52%);
}
这种写法的好处是,暗色模式只需要覆盖 --blue-l 和 --blue-s,所有依赖这个颜色的组件自动更新。
小结
颜色转换看起来是个小需求,但它贯穿前端开发的各个环节——从设计稿还原、主题系统搭建到无障碍优化。理解不同格式的设计哲学(HEX 的紧凑、RGB 的精确、HSL 的直觉),能帮你在对的场景选对的工具。
日常开发中,与其每次手动查公式或写脚本转换,不如用在线颜色转换工具一步到位。省下来的时间去处理真正有挑战的问题。
本系列其他文章: