HEX、RGB、HSL、HSV:Web 开发颜色格式详解
颜色格式概览
在 Web 开发中,我们与颜色打交道的方式远比想象的要多。CSS 支持多种颜色格式,每种都有其适用场景。理解它们的差异,能让你在编写样式、设计系统、处理用户输入时更加得心应手。
最常见的四种颜色格式是:
- HEX:
#FF5733——十六进制表示 - RGB:
rgb(255, 87, 51)——红绿蓝分量 - HSL:
hsl(11, 100%, 60%)——色相、饱和度、亮度 - HSV:
hsv(11, 80%, 100%)——色相、饱和度、明度(值)
它们都描述同一个颜色,只是编码方式不同。
HEX:最熟悉的格式
HEX(十六进制)是 Web 上最常见的颜色格式。每两个字符表示一个颜色通道(红、绿、蓝),取值范围 00–FF(十进制 0–255)。
.color {
color: #FF5733; /* 6 位标准格式 */
background: #F53; /* 3 位简写,等价于 #FF5533 */
border-color: #FF573380; /* 8 位,最后两位是 alpha 透明度 */
}
HEX 的优点是紧凑——6 个字符就能表示 1600 万种颜色。缺点是不直观:看到 #4A90E2,你很难立即知道这是什么颜色,也很难判断如何让它”亮一点”或”暗一点”。
RGB:分量式表示
RGB 直接列出红、绿、蓝三个通道的数值(0–255),并可附加 alpha 通道。
.color {
color: rgb(255, 87, 51); /* 不透明 */
background: rgba(255, 87, 51, 0.5); /* 50% 透明 */
border-color: rgb(255 87 51 / 50%); /* 现代语法 */
}
RGB 比 HEX 更易读——你能直接看到每个通道的数值。但它仍然不直观:rgb(74, 144, 226) 是什么颜色?需要经验才能判断。
HSL:为人类设计的格式
HSL(Hue-Saturation-Lightness)将颜色分解为三个更符合直觉的维度:
- 色相(Hue):0–360 度,对应色轮上的位置(0=红,120=绿,240=蓝)
- 饱和度(Saturation):0–100%,从灰色到纯色
- 亮度(Lightness):0–100%,从黑到白,50% 是纯色
.color {
color: hsl(11, 100%, 60%); /* 鲜艳的橙红色 */
background: hsla(11, 100%, 60%, 0.5); /* 50% 透明 */
border-color: hsl(11 100% 60% / 50%); /* 现代语法 */
}
HSL 的真正威力在于可编程性。想让颜色变暗?降低 Lightness。想让它更柔和?降低 Saturation。这在设计系统中特别有用:
:root {
--brand-hue: 220;
--brand-sat: 80%;
}
.button-primary {
background: hsl(var(--brand-hue), var(--brand-sat), 50%);
}
.button-primary:hover {
background: hsl(var(--brand-hue), var(--brand-sat), 45%); /* 略暗 */
}
.button-primary:active {
background: hsl(var(--brand-hue), var(--brand-sat), 40%); /* 更暗 */
}
HSV:与 HSL 的区别
HSV(Hue-Saturation-Value)与 HSL 非常相似,但”亮度”维度的定义不同:
- HSL 的 Lightness=100% 是纯白,Lightness=50% 是纯色
- HSV 的 Value=100% 是纯色,Value=0% 是纯黑
HSV 在图像处理软件(如 Photoshop)中更常见,CSS 原生不支持 HSV,但 JavaScript 库(如 d3-color、tinycolor2)通常提供转换。
纯红色:
HSL → hsl(0, 100%, 50%)
HSV → hsv(0, 100%, 100%)
两者在饱和色时差异不大,但在浅色和深色区域表现不同。HSL 更适合 CSS,HSV 更适合图像处理。
格式转换
理解转换逻辑有助于调试颜色问题。
HEX ↔ RGB
// HEX 转 RGB
function hexToRgb(hex) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return { r, g, b };
}
// RGB 转 HEX
function rgbToHex({ r, g, b }) {
const toHex = (n) => n.toString(16).padStart(2, '0');
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
console.log(hexToRgb('#FF5733')); // { r: 255, g: 87, b: 51 }
console.log(rgbToHex({ r: 255, g: 87, b: 51 })); // "#ff5733"
RGB ↔ HSL
function rgbToHsl({ r, g, b }) {
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;
let h, s;
if (max === min) {
h = s = 0; // 灰色
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100)
};
}
console.log(rgbToHsl({ r: 255, g: 87, b: 51 }));
// { h: 11, s: 100, l: 60 }
现代颜色空间
CSS Color Module Level 4 引入了新的颜色空间和函数:
/* OKLCH:感知均匀的颜色空间,适合设计系统 */
.brand {
color: oklch(65% 0.15 30);
}
/* color() 函数:访问 P3 等广色域 */
.vibrant {
color: color(display-p3 1 0.5 0);
}
/* lab / lch:基于人眼感知 */
.perceptual {
color: lab(60% 40 -30);
}
OKLCH 特别值得关注——它在感知上更均匀,调整亮度时色相不会偏移,是构建设计系统的理想选择。
颜色无障碍
选择颜色格式也影响无障碍。关键原则是确保足够的对比度。
/* WCAG AA 标准:正常文本对比度至少 4.5:1 */
.text {
color: #4A4A4A; /* 深灰 */
background: #FFFFFF; /* 白色 */
/* 对比度约 7.2:1,符合 AAA */
}
/* 大文本(18pt+ 或 14pt 粗体)对比度至少 3:1 */
.large-text {
font-size: 18pt;
color: #767676; /* 中灰 */
background: #FFFFFF;
}
HSL 在调整对比度时特别有用——降低 Lightness 通常能提高对比度,而保持色相不变。
何时用哪种格式?
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| 快速原型 | HEX | 简短、通用 |
| 设计系统、主题变量 | HSL | 易于编程调整 |
| 图像处理 | HSV/RGB | 与像素数据对应 |
| 需要透明度 | rgba/hsla | 语法清晰 |
| 现代设计系统 | OKLCH | 感知均匀,色相稳定 |
总结
没有”最好”的颜色格式,只有”最合适”的。HEX 适合快速书写,RGB 适合精确控制,HSL 适合设计系统和动态调整,HSV 适合图像处理。理解它们的转换关系,能让你在不同场景下游刃有余。
需要快速转换颜色格式?试试 CodeKit 上的 颜色转换器——支持 HEX、RGB、HSL、HSV 互转,所有计算在浏览器中完成。