顏色工具完整教學: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,配色不上傳。

實際使用流程:

  1. 開 supertools.tw/design/color
  2. 輸入品牌主色 HEX #3B82F6
  3. 點「Generate scale」自動產 OKLCH 階梯 50-900
  4. 點「Export CSS variables」一鍵複製
  5. 貼進 :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、暗模式重新設計而非反相。

延伸閱讀: