顏色工具完整教學:HEX/RGB/HSL/HSV 轉換、無障礙對比、實作
寫給:每次調 CSS 顏色都複製貼上的前端、想搞懂 HSL 比 RGB 好用在哪的設計師、需要過 WCAG AA 對比檢驗的無障礙工程師。
「為什麼設計師永遠用 HSL,工程師永遠用 HEX?」這個問題的答案藏在色彩模型的設計哲學裡。HEX 對機器友善(24 bit 緊湊表示)、RGB 對顯示器友善(直接對應紅綠藍像素)、HSL 對人類友善(直覺調整明度飽和度)、OKLCH 對未來友善(感知均勻、CSS 4 標準)。本文 13 分鐘把四種主流色彩模型、無障礙對比、配色技巧、CSS 實作一次講透。
1. 顏色模型是什麼
顏色模型(color model)是用數字表示顏色的方法。電腦顯示器用 RGB(紅綠藍三原色加色混合),印刷用 CMYK(青洋紫黃減色混合)。Web 開發主要接觸:
| 模型 | 維度 | 範例 |
|---|---|---|
| HEX | 紅綠藍各 8 bit | #FF5733 |
| RGB | 紅綠藍各 0-255 | rgb(255, 87, 51) |
| RGBA | RGB + 透明度 | rgba(255, 87, 51, 0.5) |
| HSL | 色相、飽和、亮度 | hsl(11, 100%, 60%) |
| HSV / HSB | 色相、飽和、明度 | hsv(11, 80%, 100%) |
| OKLCH | 感知亮度、彩度、色相 | oklch(63% 0.25 30) |
底層其實全是同一個 sRGB 顏色空間,差別只是「用什麼座標系表示」。
1.1 為什麼存在多種模型
每種模型有自己優勢:
- HEX:6 字元緊湊,最容易複製
- RGB:直接對應顯示硬體
- HSL:人類調色直覺(先選顏色再調亮度)
- HSV:類似 HSL 但「明度」概念對藝術家更直覺
- OKLCH:感知均勻(同樣數值差異看起來差不多)
工程師多用 HEX、設計師多用 HSL、未來會是 OKLCH。
2. 5 個核心觀念
2.1 HEX 結構
#FF5733
↓↓↓↓↓↓
↓↓↓↓└┴ B (51 = 0x33)
↓↓└┴── G (87 = 0x57)
└┴──── R (255 = 0xFF)
延伸:
- 3 位簡寫:
#F53=#FF5533(每位重複) - 8 位含 alpha:
#FF5733CC=rgba(255, 87, 51, 0.8)(CC = 204/255 = 80%)
2.2 RGB 與顯示器
每個像素含紅綠藍三個 subpixel,亮度 0-255。三者各全亮 = 白色 rgb(255,255,255),各全暗 = 黑色 rgb(0,0,0)。
CSS 寫法:
.box {
color: rgb(255, 87, 51);
background: rgb(255 87 51); /* CSS 4 無逗號 */
border-color: rgba(255, 87, 51, 0.5);
outline-color: rgb(255 87 51 / 50%); /* CSS 4 alpha */
}
2.3 HSL:人類友善
HSL 三個維度:
- H(Hue 色相):0-360°(紅 0 / 黃 60 / 綠 120 / 青 180 / 藍 240 / 洋紅 300)
- S(Saturation 飽和度):0-100%(0 = 灰、100 = 純色)
- L(Lightness 亮度):0-100%(0 = 黑、50 = 純色、100 = 白)
.primary { background: hsl(220, 80%, 50%); }
.primary-light { background: hsl(220, 80%, 70%); }
.primary-dark { background: hsl(220, 80%, 30%); }
同色不同亮度只改 L,配色非常直覺。HEX 做同樣事要算紅綠藍各幾。
2.4 OKLCH:感知均勻
RGB / HSL 的問題:數值差異 ≠ 視覺差異。例如綠色 hsl(120, 100%, 50%) 看起來比藍色 hsl(240, 100%, 50%) 亮很多,明明 L 相同。
OKLCH(2020 Björn Ottosson 提出)解決這個問題:
.box { background: oklch(63% 0.25 30); }
/* ↑ ↑ ↑ */
/* L C H */
/* 亮度 chroma 色相 */
- L:感知亮度(0-100%)
- C:彩度(0-0.4 左右)
- H:色相(0-360°)
特性:
- 同樣 L 數值 → 視覺亮度真的接近
- 適合做色彩階梯(design token)
- CSS Color 4 標準,2026 年所有主流瀏覽器支援
:root {
--primary-50: oklch(95% 0.05 250);
--primary-100: oklch(90% 0.10 250);
--primary-500: oklch(60% 0.20 250);
--primary-900: oklch(25% 0.15 250);
}
2.5 對比度(WCAG)
對比度(contrast ratio)= 兩個顏色亮度比值,範圍 1:1 - 21:1。
WCAG 2.2 標準:
| 等級 | 一般文字 | 大文字 (18pt+) | UI 元素 |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4.5:1 | - |
範例:
背景 #FFFFFF + 文字 #333333 = 12.6:1 ✓ AAA
背景 #FFFFFF + 文字 #777777 = 4.5:1 ✓ AA
背景 #FFFFFF + 文字 #999999 = 2.8:1 ✗ 不過
工程上:用對比工具驗證,淺色背景配深色文字最安全。
3. 實戰範例
範例 1:JavaScript HEX ↔ RGB 互轉
function hexToRgb(hex) {
hex = hex.replace(/^#/, "");
if (hex.length === 3) hex = hex.split("").map(c => c + c).join("");
const num = parseInt(hex, 16);
return {
r: (num >> 16) & 255,
g: (num >> 8) & 255,
b: num & 255,
};
}
function rgbToHex(r, g, b) {
return "#" + [r, g, b].map(x => x.toString(16).padStart(2, "0")).join("");
}
console.log(hexToRgb("#FF5733")); // {r:255, g:87, b:51}
console.log(rgbToHex(255, 87, 51)); // "#ff5733"
範例 2:RGB → HSL
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
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 *= 60;
}
return { h: Math.round(h), s: Math.round(s * 100), l: Math.round(l * 100) };
}
console.log(rgbToHsl(255, 87, 51)); // {h:11, s:100, l:60}
範例 3:Python 顏色運算
import colorsys
# HSV → RGB(0-1 範圍)
r, g, b = colorsys.hsv_to_rgb(11/360, 0.8, 1.0)
print(int(r*255), int(g*255), int(b*255))
# RGB → HSL
h, l, s = colorsys.rgb_to_hls(255/255, 87/255, 51/255)
print(h*360, s*100, l*100)
範例 4:WCAG 對比度計算
function luminance(r, g, b) {
const a = [r, g, b].map(v => {
v /= 255;
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
});
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}
function contrast(rgb1, rgb2) {
const L1 = luminance(...rgb1);
const L2 = luminance(...rgb2);
return (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);
}
console.log(contrast([255,255,255], [51,51,51]).toFixed(2)); // 12.63
console.log(contrast([255,255,255], [153,153,153]).toFixed(2)); // 2.85 ✗
範例 5:CSS 變數系統
:root {
/* base color */
--hue: 220;
/* gradient */
--c-50: hsl(var(--hue), 100%, 96%);
--c-100: hsl(var(--hue), 100%, 90%);
--c-300: hsl(var(--hue), 80%, 70%);
--c-500: hsl(var(--hue), 80%, 50%);
--c-700: hsl(var(--hue), 80%, 30%);
--c-900: hsl(var(--hue), 60%, 15%);
}
button { background: var(--c-500); }
button:hover { background: var(--c-700); }
換主題只需改 --hue。
4. 進階技巧
4.1 配色理論
從色相環找配色:
| 配色法 | 規則 | 適用 |
|---|---|---|
| 單色(Monochromatic) | 同色相不同明度 | 簡約風 |
| 互補(Complementary) | 180° 對面 | 強對比 |
| 三分(Triadic) | 120° 三色 | 活潑 |
| 四分(Tetradic) | 90° 四色 | 複雜 |
| 類比(Analogous) | 相鄰 30°-60° | 自然 |
HSL 算配色超簡單:
const baseHue = 220;
const complementary = (baseHue + 180) % 360;
const triadic = [baseHue, (baseHue + 120) % 360, (baseHue + 240) % 360];
const analogous = [-30, 0, 30].map(d => (baseHue + d + 360) % 360);
4.2 色覺友善(色盲檢驗)
8% 男性、0.5% 女性有色覺異常(多為紅綠色盲)。配色避免:
- 紅綠單獨區分(用形狀 / 圖示輔助)
- 黃藍對比(藍黃色盲難分)
工具:Coblis 模擬色盲視覺。
4.3 暗色模式(dark mode)
:root {
--bg: hsl(0, 0%, 100%);
--fg: hsl(0, 0%, 10%);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: hsl(220, 15%, 12%);
--fg: hsl(220, 15%, 90%);
}
}
body {
background: var(--bg);
color: var(--fg);
}
暗色模式不只是把白變黑:
- 純白文字
#FFF在暗底太刺眼,用hsl(0,0%,90%) - 純黑底
#000反差太強,用hsl(220,15%,12%)微藍
4.4 CSS color-mix(CSS 4)
.button {
background: color-mix(in oklch, var(--primary), white 20%);
}
color-mix 在 OKLCH 空間混色,比 RGB 混色感知正確。
4.5a 漸層(gradient)的色彩空間
CSS 漸層預設在 sRGB 空間插值,常產生「灰色 band」:
/* 從藍到黃在 RGB 空間經過灰色 */
background: linear-gradient(to right, blue, yellow);
CSS Color 4 允許指定色彩空間:
background: linear-gradient(in oklch to right, blue, yellow);
OKLCH 插值經過鮮豔的綠色,視覺更自然。
4.5b CSS relative color syntax
CSS 4 新語法 from:
.primary { color: #3B82F6; }
.primary-hover {
color: oklch(from #3B82F6 calc(l - 0.1) c h);
/* 亮度降 10% 其他保持 */
}
不需 SASS 或 JS 預處理,純 CSS 算 color variant。
4.5 P3 廣色域
新螢幕(MacBook、iPhone、現代 OLED)支援 Display P3 色域(比 sRGB 大 25%):
.vivid {
color: color(display-p3 1 0 0); /* 比 sRGB 紅更鮮豔 */
}
不支援的螢幕會 fallback 到 sRGB。
5. 常見錯誤與解法
錯誤 1:透明度寫成 #FFFFFF55
症狀:舊瀏覽器顯示亂色。
根因:IE / 舊 Safari 不支援 8-digit HEX。
解法:用 rgba() / hsla()。
錯誤 2:對比不過 WCAG
症狀:淺灰文字看不清。 根因:設計師憑感覺挑顏色。 解法:用對比工具驗證,至少達 AA 4.5:1。
錯誤 3:色彩階梯不均勻
症狀:blue-100 到 blue-200 看起來變化大,blue-800 到 blue-900 卻幾乎一樣。 根因:HSL L 數值差等距 ≠ 視覺差等距。 解法:用 OKLCH 設計 design token。
錯誤 4:印刷顏色不對
症狀:CSS HEX 跟印刷 CMYK 看起來差很多。 根因:色域不同(sRGB vs CMYK)。 解法:印刷品給 Pantone 色號或 CMYK 數值,HEX 只做螢幕參考。
錯誤 5:暗模式直接反相
症狀:白底黑字直接反成黑底白字,看起來反差過強。
根因:純黑配純白對眼睛刺激。
解法:暗模式背景用深藍灰(hsl(220,15%,12%)),文字用淺灰(hsl(0,0%,90%))。
6. 用 SuperTools 線上版完成相同任務
設計時需要快速轉換顏色?打開 SuperTools 顏色工具:
- 多格式互轉:HEX / RGB / HSL / HSV / OKLCH / CMYK 雙向
- Color Picker:拖選顏色即時看所有格式
- 對比度檢驗:輸入兩個顏色,自動標 AA / AAA pass / fail
- 配色方案產生:選 base color 自動產 mono / complementary / triadic
- 色盲模擬:1 鍵切換三種色盲視角
- CSS 變數匯出:產 design token JSON / CSS / Tailwind config
- OKLCH 階梯:選 hue + chroma,自動產 50-950 階梯
工具 client-side,配色不上傳。
實際使用流程:
- 開 supertools.tw/design/color
- 輸入品牌主色 HEX
#3B82F6 - 點「Generate scale」自動產 OKLCH 階梯 50-900
- 點「Export CSS variables」一鍵複製
- 貼進
:root {}完成 design token
立即使用 SuperTools 顏色工具:https://supertools.tw/design/color
7. 其他語言實作
Python
import colorsys
colorsys.rgb_to_hsv(1.0, 0.34, 0.2)
colorsys.hls_to_rgb(0.04, 0.6, 1.0)
Node.js(color 套件)
const Color = require("color");
Color("#FF5733").hsl().string(); // 'hsl(11, 100%, 60%)'
Color("#FF5733").lighten(0.2).hex();
Go(go-colorful)
import "github.com/lucasb-eyer/go-colorful"
c, _ := colorful.Hex("#FF5733")
h, s, l := c.Hsl()
Rust(palette crate)
use palette::{Srgb, Hsl, IntoColor};
let rgb = Srgb::new(1.0, 0.34, 0.2);
let hsl: Hsl = rgb.into_color();
CSS
color: hsl(11 100% 60%);
color: oklch(63% 0.25 30);
color: color-mix(in oklch, red 50%, blue 50%);
8. FAQ
Q1:HEX 跟 RGB 哪個快? 等價,渲染速度無差。HEX 字串短一點。
Q2:HSL 跟 HSV 哪個好? HSL 更常用(CSS 內建),HSV 在繪圖軟體常見。
Q3:OKLCH 已可生產用?
2024 後主流瀏覽器全支援,舊瀏覽器用 @supports fallback。
Q4:要全部改 OKLCH 嗎? 新專案 design token 推薦 OKLCH,現有 HEX 不必急著換。
Q5:色彩管理(ICC profile)需要做嗎? 一般 Web 不用。攝影 / 高端設計才需要。
9. 實戰案例研究
案例 1:電商重設計暗模式失敗
某台灣電商 2024 年推暗模式,純粹把 #FFF 換 #000、#000 換 #FFF。上線後 user 反映:
- 商品圖背景變黑後對比過強,眼睛刺激
- 紅色「立即購買」按鈕變得太亮像螢光
- 折扣標籤的橘色直接「灼燒」
修法(OKLCH 重做):
:root[data-theme="dark"] {
--bg-primary: oklch(15% 0.02 220); /* 深藍灰 */
--bg-card: oklch(20% 0.02 220); /* 比背景稍亮 */
--text-primary: oklch(92% 0.01 220); /* 略暖白 */
--accent: oklch(65% 0.18 25); /* 紅降亮度 */
--warning: oklch(75% 0.15 60); /* 橘降彩度 */
}
教訓:暗模式不是反相,是重新設計色盤。
案例 2:無障礙改造後流量提升
某政府網站 2025 改造,原本灰色文字 #999(對比 2.85:1,不過 AA)改為 #444(對比 9.7:1):
- 60 歲以上 user 停留時間 +40%
- 閱讀完整度(scroll depth)+25%
- 退出率 -18%
提醒:對比不只為視障,對所有 user 都更友善。
案例 3:design token 從 HSL 遷移 OKLCH
某新創 design system 用 HSL 階梯:
--blue-50: hsl(220, 100%, 96%);
--blue-500: hsl(220, 80%, 50%);
--blue-900: hsl(220, 60%, 15%);
發現 blue-100 → blue-200 視覺差大,blue-700 → blue-800 幾乎看不出差。改 OKLCH 後均勻很多:
--blue-50: oklch(97% 0.02 250);
--blue-100: oklch(92% 0.05 250);
--blue-200: oklch(87% 0.09 250);
--blue-300: oklch(80% 0.13 250);
--blue-400: oklch(72% 0.17 250);
--blue-500: oklch(62% 0.20 250);
--blue-600: oklch(52% 0.18 250);
--blue-700: oklch(42% 0.16 250);
--blue-800: oklch(32% 0.13 250);
--blue-900: oklch(22% 0.10 250);
L 軸每階差 10%,視覺差也接近線性。
10. 結論 + 延伸閱讀
色彩工具是設計師與工程師的橋樑。掌握 HEX / RGB / HSL / OKLCH 四種模型,知道何時用哪個(HEX 給機器、HSL 給人、OKLCH 給未來),加上 WCAG 對比檢驗,就能做出兼具美感與可訪性的介面。下次調色時,先到 SuperTools 線上工具試配色方案,再貼進 CSS。記住三條原則:對比優先、用 OKLCH 設計 token、暗模式重新設計而非反相。
延伸閱讀: