HEX 与 RGB 与 HSL 与 OKLCH — 每种 CSS 颜色格式何时真正有意义
HEX在CSS中无处不在,但它通常不是最佳选择。何时使用HEX、RGB、HSL以及新的OKLCH——以及为什么Tailwind v4将其颜色配色改为OKLCH。
打开任何由2011年从W3Schools学习CSS的人编写的代码库,你将发现一堵 #rrggbb 值的墙。HEX无处不在——不是因为它在任务中是最好的格式,而是因为在我们第一次接触CSS时,所有的教程和颜色选择器都使用了这种格式。它仍然有效,不会消失。但在2026年,使用HEX来 万物 就像在没有 const 的情况下编写JavaScript一样,因为你学习的是2009年的博客文章。
有四种值得了解的颜色格式:HEX、RGB、HSL和OKLCH。每一种格式在特定情况下是正确的选择,在其他情况下则是错误的。以下是何时使用哪种格式。
HEX (#rrggbb / #rrggbbaa)
HEX以十六进制数字对的形式编码颜色:红色两个,绿色两个,蓝色两个。 #ff5733 转换为 rgb(255, 87, 51) ——一种橙红色。如果没有打开颜色选择器,你无法读取这个值;你只能记住它。
有一种简写形式: #f53 扩展为 #ff5533。只有当每对数字都相同才有效。透明度是第四对: #ff5733cc ——其中 cc 是alpha通道。对于那些在家记分的人来说,这大约是80%的不透明度(0xCC / 0xFF ≈ 0.8)。完全有效,但完全无法阅读。
当HEX适用时
- 来自Figma或Sketch的设计令牌。 设计师导出HEX。你直接粘贴HEX。这就是工作流程。不要抗拒它。
- 在值是静态且视觉工具控制的情况下。 如果VS Code的颜色选择器或浏览器开发者工具是产生该值的工具,HEX是合适的。
- 第三方集成 仅接受HEX输入。
当HEX是错误的选择时
- 在程序化修改颜色时——你无法合理地对
#ff5733 - 进行数学运算
- 表达色调关系——没有直观的方法来推导出更亮或更暗的变体
构建具有语义令牌的设计系统
RGB / RGBA rgb(255, 87, 51) RGB以纯十进制形式明确表示相同的红色、绿色、蓝色通道。 #ff5733与 rgb(255 87 51)是相同的橙红色,但通道值至少是人类可读的数字。现代CSS颜色级别4语法去掉了逗号: rgb(255 87 51 / 50%)。透明度用斜线表示: rgba(255, 87, 51, 0.5) 。旧的
仍然有效——浏览器尚未弃用它,也不会弃用。
- 当RGB适用时 在JavaScript中的颜色操作。
- 当你需要通过与白色混合来调整亮度时:你可以直接对通道值进行算术运算。 Canvas和WebGL。
- 这些API处理0到255的整数或0到1的浮点数。RGB直接映射到底层像素管道所期望的值。 当你从硬件传感器或图像库获取通道值时
并且不需要转换。
- 当RGB是错误的选择时
- 设计配色方案——没有直观的视觉心理模型来理解小幅度RGB调整看起来是什么样子
深色模式主题——你需要重新计算所有三个通道以改变亮度
HSL (色调 / 饱和度 / 明度) hsl(14 100% 60%) HSL是第一个映射到人类如何思考颜色的颜色格式。色调是色轮上的角度(0–360°),饱和度控制颜色的鲜艳程度(0% = 灰色,100% = 纯色),明度控制颜色的亮度(0% = 黑色,100% = 白色)。
是相同的橙红色。
:root {
--brand-hue: 14;
--brand-saturation: 100%;
--brand-400: hsl(var(--brand-hue) var(--brand-saturation) 70%);
--brand-500: hsl(var(--brand-hue) var(--brand-saturation) 60%);
--brand-600: hsl(var(--brand-hue) var(--brand-saturation) 50%);
--brand-700: hsl(var(--brand-hue) var(--brand-saturation) 40%);
}
实际优势:如果你想获得颜色的较暗版本,就降低明度值。想要一种柔和版本?降低饱和度。你可以从单一色调值推导出完整的色调系列。这就是为什么基于HSL的CSS自定义属性系统如此常见: hsl(14 100% 60% / 50%).
透明度的处理方式与其他格式相同: hsl(60 100% 50%) 有一个真实的限制:HSL的明度尺度不是感知均匀的。两个具有相同L值的颜色在亮度上可能看起来非常不同——尝试将 hsl(240 100% 50%) (黄色) 和
(蓝色) 并排。黄色看起来明显更亮,尽管它们的L=50%相同。这对无障碍设计尤其重要,特别是对颜色渐变。
- 当HSL适用时 颜色系统和设计令牌。
- 上述单色调系列模式是直观且易读的。 深色模式主题。
- 只需更改L值,保持其他不变。这样就能干净地工作。 CSS自定义属性中的色调和阴影
——这是它最初设计的用例。
OKLCH —— 现代替代方案 oklch(0.65 0.18 28) OKLCH是HSL本该成为的样子。它以三个值描述颜色:明度(0–1)、色度(类似于饱和度,大约0–0.4)和色调(0–360°)。
大约是相同的橙红色。
- 与HSL的关键区别在于感知均匀性。在OKLCH中,两个具有相同L值的颜色在人眼看来亮度相同。L=0.65的黄色和L=0.65的蓝色看起来亮度相似——而HSL中黄色会显得更亮。这对两种具体场景很重要: 无障碍设计。
- 当你基于L值计算对比度时,这些值反映了用户实际感知到的内容,而不仅仅是数学计算的结果。 渐变。
从蓝色到黄色的HSL渐变在中间会经过一个灰暗的区域。而OKLCH中的相同渐变则始终保持鲜艳,因为中间步骤的感知亮度保持一致。
截至2023年的浏览器支持情况:所有现代浏览器(Chrome 111+,Firefox 113+,Safari 15.4+)。不支持IE11——而2026年没有人还在为IE11开发新代码。
Tailwind v4已将其整个颜色体系迁移到OKLCH。这不是一个微小的实现细节——这是目前最广泛使用的CSS框架发出的信号,表明这是颜色体系的正确方向。 CSS 渐变生成器 如果你正在构建或实验HSL或OKLCH渐变,
在IO Tools上支持两种格式——有助于并排查看渐变质量的差异。
- 新建的设计系统从零开始构建。 如果你今天正在定义你的颜色令牌,OKLCH能提供HSL所不具备的感知均匀性。
- 以渐变为主的UI。 渐变质量的差异是明显且有意义的。
- 无障碍颜色配色方案 你需要对比度比例反映实际的视觉感知。
四种格式中的同一种颜色
这里展示的是 rgb(255, 87, 51) ——一种温暖的橙红色——在所有格式中的表达,带有50%透明度变体:
| 格式 | 纯色 | 50% 透明 |
|---|---|---|
| 十六进制 | #ff5733 | #ff573380 |
| RGB | rgb(255 87 51) | rgb(255 87 51 / 50%) |
| 高速链路 | hsl(14 100% 60%) | hsl(14 100% 60% / 50%) |
| OKLCH | oklch(0.65 0.18 28) | oklch(0.65 0.18 28 / 50%) |
请注意,当你需要将颜色变暗20%时,你会希望手动编辑哪一个。HEX:你需要打开颜色选择器。RGB:你需要对三个值进行算术运算。HSL:将L值从60%改为40%。OKLCH:将L值从0.65改为0.45。HSL和OKLCH版本直接表达了意图。
实际的迁移路径
不要重构你现有的HEX值。它们是有效的,没有问题,而且这种变更的回报率几乎为零。请保留它们。
对于新项目,应用以下规则:
- 来自设计师或设计工具的静态颜色 → HEX。 直接粘贴Figma提供的内容。无需转换。
- 在JavaScript中操作或传递给canvas/WebGL的颜色 → RGB。 通道级别的数学运算可以无缝映射。
- 新的CSS自定义属性和设计令牌 → HSL或OKLCH。 你希望能够在不重新计算三个独立值的情况下推导出色调和阴影版本。
- 从零开始构建的新设计系统,或以渐变为主的项目 → OKLCH。 感知均匀性值得付出轻微的学习曲线来掌握色度值。
在新项目中CSS自定义属性的一个具体模式:
:root {
/* Define the base in OKLCH */
--brand: oklch(0.65 0.18 28);
/* Derive tonal variants by adjusting L */
--brand-light: oklch(0.78 0.14 28);
--brand-dark: oklch(0.48 0.20 28);
--brand-muted: oklch(0.65 0.08 28);
/* Transparency with the slash syntax */
--brand-ghost: oklch(0.65 0.18 28 / 15%);
}
这既可读,又无需工具即可编辑,并且比等效的HSL方法产生更好的渐变。
底线
HEX并没有错——它只是专门化了。它被优化用于从视觉工具获取并粘贴到代码中的值,而不是用于你思考或修改的值。RGB在你需要与JavaScript或canvas API交互时非常有用。HSL在现有代码库中使用它时仍然是一个可靠的选择。对于新设计系统,OKLCH是你的目标。
采用HSL或OKLCH的障碍比看起来要小。你不需要迁移任何内容——只需在你编写下一组令牌时开始使用它们。 Color Picker 在IO Tools上的
