写 CSS 的时候填颜色,最常见的就是 HEX、RGB、HSL 这三种写法。它们能表示的颜色其实完全一样,都是约 1677 万种,区别只在写法和用起来的顺手程度。很多人习惯了一种就一直用,但其实不同场景下选对格式能省不少事。
需要快速转换几种格式的话,可以用 速工具 的颜色转换工具,输入任意一种格式自动算出另外两种。
三种格式分别长什么样
拿一个橙色来举例,三种写法:
/* HEX —— 十六进制 */
color: #FF8800;
/* RGB —— 红绿蓝分量,0-255 */
color: rgb(255, 136, 0);
/* HSL —— 色相/饱和度/亮度 */
color: hsl(33, 100%, 50%);
三种写法渲染出来是同一个颜色,浏览器一视同仁。选择哪种,纯粹是看你接下来要干嘛。
各自的优缺点
HEX:最短最紧凑,Figma、Sketch 这些设计软件默认复制的格式。缺点是不直观——看到 #FF8800 你很难立刻反应过来是什么颜色,想调亮一点更不知道该改哪几位。
RGB:能看清红绿蓝三个通道各是多少,写 JS 做颜色计算时比较方便。缺点跟 HEX 类似,调亮度不直观,而且写法比 HEX 长。
HSL:把颜色拆成色相(H)、饱和度(S)、亮度(L)三个维度,跟人脑理解颜色的方式对齐。想"亮一点"就把 L 调大,想"淡一点"就把 S 调小,非常直观。缺点是设计师一般不按 HSL 思维工作,沟通时可能要转换一下。
什么时候用 HEX
从设计稿拿颜色的时候,直接复制 HEX 最省事,不用手动拆。写静态的颜色变量、定义品牌色板、给元素填一个不变的颜色,HEX 都很合适。
:root {
--brand-primary: #FF8800;
--brand-dark: #1a1a2e;
--text-default: #333333;
}
HEX 最大的优势就是短。在一个大项目里,颜色值出现几百次,HEX 比 rgb() 能省不少字符量,文件也更小。
什么时候用 RGB/RGBA
需要透明度的时候。虽然 HEX 也有 8 位写法(#FF880080),但最后两位是十六进制的透明度值,要自己算 0.5 × 255 = 128 = 0x80,不直观。RGBA 直接写小数,一目了然:
/* 半透明橙色背景 */
background: rgba(255, 136, 0, 0.5);
/* 80% 不透明的遮罩层 */
.overlay {
background: rgba(0, 0, 0, 0.8);
}
另外,如果你要在 JS 里动态计算颜色(比如根据数据改变红色通道的值),RGB 的分量写法比 HEX 方便处理。
什么时候用 HSL
调色和生成配色方案的时候,HSL 是最顺手的。因为它的三个维度和人脑对颜色的感知对齐,改起来很自然。
比如按钮 hover 时想让颜色亮一点:
.btn {
background: hsl(210, 80%, 50%);
}
.btn:hover {
/* 只改亮度,色相和饱和度不动 */
background: hsl(210, 80%, 60%);
}
如果用 HEX,你得从 #1a73e8 猜一个更亮的值 #4a90f0,根本看不出规律。HSL 只改一个数字,明明白白。
生成一组同色系配色也很方便——固定 H 和 S,调不同的 L 值就能得到从深到浅的一整套色阶:
--color-900: hsl(210, 80%, 20%);
--color-700: hsl(210, 80%, 35%);
--color-500: hsl(210, 80%, 50%);
--color-300: hsl(210, 80%, 70%);
--color-100: hsl(210, 80%, 90%);
CSS 新增的颜色函数
最近几年 CSS 加了几个新的颜色相关能力,用好了能让代码干净不少。
color-mix():直接在 CSS 里混合两个颜色,不用再开计算器或者预处理器:
/* 把蓝色和白色混 20%,得到一个浅蓝 */
--hover-bg: color-mix(in srgb, #1a73e8 80%, white);
以前做 hover 浅色版本要手算或用工具调,现在一行搞定。支持 srgb、oklab 等多种混合空间。
oklch():比 HSL 更先进的颜色空间。HSL 有个老问题——亮度不均匀,同样的 L=50%,黄色看起来比蓝色亮得多。oklch 基于人眼感知模型,同样的亮度值对应的视觉明度是一致的,调出来的配色更和谐:
--primary: oklch(70% 0.15 250);
--primary-hover: oklch(75% 0.15 250);
color() 函数:可以访问 sRGB 以外的色彩空间,比如 Display P3(更广的色域),在支持的屏幕上能显示更鲜艳的颜色。
--vivid: color(display-p3 1 0 0);
这些新函数在 Chrome、Safari、Firefox 的新版本里都已经支持了。如果要做老浏览器兼容,用 @supports 做个降级就行。
常见问题 FAQ
HEX、RGB、HSL 能表示的颜色数量一样吗?
完全一样,都是约 1677 万种(256 × 256 × 256)。HEX 的每两位对应 RGB 的一个通道,#FF8800 就是 rgb(255, 136, 0)。HSL 只是换了一种描述方式,底层还是映射到同一组 RGB 值。所以选哪个不影响能用的颜色范围。
CSS 变量配合 HSL 怎么用最好?
推荐把色相、饱和度、亮度分别存成变量,用的时候拼起来。这样改主题色只要动一个值:--h: 210; --s: 80%; --l: 50%;,然后 color: hsl(var(--h) var(--s) var(--l));。做暗黑模式时只要调 L 值就行,非常灵活。
设计稿给的 HEX 要不要转成 HSL 再写进 CSS?
没必要特意转。如果这个颜色是静态的、不会变,直接用 HEX 就行,少一步转换。只有当你需要基于这个颜色派生出一系列变体(hover、disabled、浅色背景版)时,转成 HSL 才更方便调。
color-mix() 在老浏览器上会怎样?
不支持的浏览器会忽略这条声明,元素会回退到没有这个属性的默认样式。如果想做平滑降级,先写一个 HEX 备选值,再用 @supports (color: color-mix(in srgb, red, blue)) 覆盖。不过现在主流浏览器的覆盖率已经很高了,新项目一般不用太担心。