カラーコード完全理解 — HEX / RGB / HSV / CSS 変数

カラフルなパレット Photo: Unsplash

デザイナから渡ってきた Figma を CSS に起こしていたら「プライマリカラーを 10% 明るくして」と言われて固まったこと、ありませんか。HEX で書かれた #2563eb をどう「10% 明るく」すればいいのか、RGB で書き直してみても全部同じだけ足したら微妙に色味がズレる、HSL に変換してみたら今度は彩度が落ちる気がする——カラーコードの世界はパッと見シンプルなのに、一歩踏み込むと沼です。本記事では HEX / RGB / HSL / HSV / OKLCH といった表記法の違いから、CSS 変数でテーマを組む方法、WCAG のコントラスト比、カラーブラインドへの配慮まで、実務でつまずきがちな論点をまとめて整理します。「なぜ HSV はデザイナに人気なのか」を自信を持って説明できるようになるのがゴールです。

なぜ Web の色は #RRGGBB なのか

Web で色を表記するときに #RRGGBB の 6 桁 16 進が定番なのは、1990 年代のディスプレイ事情にさかのぼります。当時主流だった True Color は「R・G・B 各チャンネル 8 ビット、合計 24 ビット = 1677 万色」という設計で、これはちょうど人間の目がグラデーションを連続的に感じられる実用上限とされていました。16bpp ハイカラー(6.5 万色)や 8bpp インデックスカラー(256 色パレット)も併用されていましたが、CPU とビデオメモリが十分に安くなった 1996 年の CSS Level 1#RRGGBB#RGBrgb()・名前付き 16 色が採用され、以降 30 年近く「Web の色といえば HEX」の時代が続いています。16 進 2 桁が 1 チャンネルを表すこの表記は、打ちやすさ・読みやすさ・コピペのしやすさ、いずれも実用的な落とし所として生き残っているわけです。

カラーモデルの基礎(加法 vs 減法)

色の話を始めると必ず最初に出てくるのが「加法混色」と「減法混色」の違いです。名前は堅苦しいですが、中身はシンプルで「光を足して色を作るのか、光を引いて色を作るのか」の違いでしかありません。ディスプレイと紙で色の扱いがまったく違うのは、この 2 つが根本的に別ゲームだからです。

加法混色は光そのものを混ぜる方式で、赤・緑・青(RGB)の三原色を使います。モニタの 1 ピクセルは実際にはこの 3 色の小さなサブピクセルで構成されていて、それぞれの明るさを調整することで数百万色を表現します。R・G・B をすべてフルにすれば白、すべて 0 にすれば黒。真ん中の等量混合になると灰色になり、2 色を混ぜると黄(R+G)・シアン(G+B)・マゼンタ(B+R)が現れます。身の回りで加法混色を使うのは、モニタ・テレビ・プロジェクタ・スマートフォンの画面・LED 照明など、自ら光を発する機器すべてです。

減法混色はその逆で、白い紙に塗られたインクが「白色光のうち特定の波長を吸収して、残りを反射する」ことで色を作ります。使う三原色はシアン・マゼンタ・イエロー(CMY)で、3 色を重ねると理論上は黒になりますが、実際には濁った茶色にしかならないため、純粋な黒インク(K = Key plate)を追加した CMYK が印刷の標準です。紙・本・ポスター・雑誌など、反射光で見るものは全部こちらの仲間です。

この違いが厄介なのは「モニタでは鮮やかに見えた色が、印刷するとくすむ」という経験を全員が一度はすることです。モニタの sRGB が表現できる色域(ガマット)と、CMYK インクで再現できる色域は重なりが不完全で、特にモニタの鮮やかな青や緑は印刷で落ちがちです。だからこそ印刷物のデザインは最初から CMYK で作る、モニタ向けは RGB で作る、と入り口から分けるのが鉄則になっています。

もう一歩踏み込むと、同じ「RGB」でも色空間によってカバー範囲が違います。Web の標準は sRGB(1996 年策定)で、ほぼすべての一般的なモニタが共通で再現できる最低ラインです。最近の iPhone や MacBook は Display P3 という一回り広い色空間をサポートしていて、特に鮮やかな赤やオレンジで sRGB では出せない領域を描けます。CSS Colors Level 4 以降は color(display-p3 1 0 0) のように色空間を明示できるので、広色域ディスプレイ向けに攻めた色を指定することも可能です。一方で古いモニタや Windows の一部環境ではこの領域が正しく表示されないので、フォールバックを用意するのが実務的な運用になります。

HEX 記法(#RRGGBB#RGB

HEX 記法は Web でいちばん馴染みのある色表記です。基本は #RRGGBB の 6 桁で、先頭の # に続けて R・G・B 各チャンネルを 16 進数 2 桁で並べます。16 進 2 桁は 00 から FF まで、10 進に直すと 0〜255 の 256 階調。これが 各チャンネル 8 ビットという設計の表れで、3 チャンネルあわせて 24 ビット = 約 1677 万色を表現できます。

短縮形として #RGB の 3 桁記法もあります。これは「各チャンネルの 2 桁を同じ文字で揃えた場合」のシンタックスシュガーで、#F00#FF0000#FFF#FFFFFF を意味します。表現できる色は 16 × 16 × 16 = 4096 色に限定されるので、細かい色調整には向きませんが、プロトタイプやドキュメントの本文中でサクッと色を指定したいときは便利です。

CSS Colors Level 4(2016 年以降の草案)で追加されたのが、アルファ付きの 8 桁・4 桁記法です。#RRGGBBAA の末尾 2 桁がアルファチャンネル(0-255)で、#2563ebCC なら「#2563eb をアルファ 80%(CC = 204 / 255 ≒ 0.8)」という意味になります。#RGBA の 4 桁記法も同様に対応しており、#F008#FF000088(赤・アルファ 53%)を表します。モダンブラウザは全てこの記法をサポートしているので、RGBA 関数記法の代わりにサクッと書きたいときに使えます。

大文字と小文字は区別されません。#FF0000#ff0000 はまったく同じ色です。チーム内でどちらに統一するかは好みですが、CSS のリンター(Stylelint など)では color-hex-case で強制できるので、一貫性を保ちたいなら設定しておくと事故が減ります。個人的には小文字派が多い印象ですね。

記法対応
6 桁 #RRGGBB#2563ebCSS 1 以降(ほぼ全ブラウザ)
3 桁 #RGB#F00CSS 1 以降(ほぼ全ブラウザ)
8 桁 #RRGGBBAA#2563ebCCCSS Colors Level 4(モダンブラウザ)
4 桁 #RGBA#F008CSS Colors Level 4(モダンブラウザ)

HEX の実装を書くなら、JavaScript では次のように文字列操作で簡単に RGB に戻せます。

// HEX → RGB の最短実装
const hex = '#2563eb';
const r = parseInt(hex.slice(1, 3), 16); // 37
const g = parseInt(hex.slice(3, 5), 16); // 99
const b = parseInt(hex.slice(5, 7), 16); // 235

// RGB → HEX(逆方向)
const toHex = (n) => n.toString(16).padStart(2, '0');
const hexStr = '#' + toHex(37) + toHex(99) + toHex(235); // "#2563eb"

短縮形を受け付ける堅牢な実装にしたいなら、.length が 4 なら各文字を 2 回繰り返してから同じロジックに流す、というワンステップを加えるだけで済みます。プロダクションで使うなら chroma.jscolord のようなライブラリに任せるのが無難ですが、「30 行くらいで自前実装できる」ということを知っておくと、いざというとき強いです。

RGB / RGBA(0-255 vs 0.0-1.0)

CSS で HEX と並んでよく使うのが rgb() 関数記法です。基本形は rgb(255, 0, 0) のように 3 つの整数を並べるだけ。各値は 0〜255 の範囲をとり、HEX の 16 進表現と 1 対 1 で対応します。#FF0000rgb(255, 0, 0) はまったく同じ色です。

CSS Colors Level 4 で コンマなし記法が追加されました。rgb(255 0 0) のようにスペース区切りで書けるようになり、さらにアルファを / で区切って書けます。rgb(255 0 0 / 0.5) は「赤・不透明度 50%」。従来の rgba(255, 0, 0, 0.5) と同じ意味ですが、新しい書き方では rgbrgba の区別がなくなり、アルファは任意で付け足す形になります。

値の指定方法はもう少し柔軟で、0〜255 の整数だけでなく 0〜100% のパーセントでも書けます。rgb(100% 0% 0%)rgb(255 0 0) と同じ。さらに CSS Colors Level 4 では none キーワードや相対色記法(rgb(from var(--primary) r g b / 0.5))もサポートされました。全部覚える必要はありませんが、「CSS の色記法はここ数年でかなり進化している」という感覚だけでも持っておくと、コードレビューで「この書き方あり?」となったときに焦らずに済みます。

一方で、他のプログラミング環境に目を向けると RGB の値域はバラバラです。CSS や多くのグラフィックソフト(Photoshop、Figma)は 0-255 の整数が標準ですが、WebGL / OpenGL / Canvas の WebGPU 版のように GPU に近いレイヤーでは 0.0-1.0 の浮動小数点が標準になります。単に 255 で割るだけですが、スライダーや API を跨ぐときに「あれ、真っ赤が 1.0 なの 255 なの」と混乱しやすいので、扱っている値の単位を意識する癖をつけておきましょう。

/* CSS の代表的な書き方(全部同じ色) */
.a { color: #2563eb; }
.b { color: rgb(37, 99, 235); }
.c { color: rgb(37 99 235); }           /* Level 4 コンマなし */
.d { color: rgb(14.5% 38.8% 92.2%); }   /* パーセント */
.e { color: rgb(37 99 235 / 0.8); }     /* アルファ 80% */
.f { color: rgba(37, 99, 235, 0.8); }   /* 従来記法 */

アルファ値の表現も微妙に揺らぎがあります。CSS では 0.550% が等価で、どちらも 50% の不透明度を意味します。HEX の 8 桁記法では 2 桁 16 進(00FF)になるので、0.580(=128)です。変換するときに小数と 16 進が混ざるのがややこしいですが、「0.5 ≒ 80」「0.8 ≒ CC」「0.25 ≒ 40」あたりを覚えておくと読み書きが速くなります。

HSL / HSV 直感的な指定

RGB や HEX は「マシンが理解しやすい」表記ですが、人間が頭の中で色を組み立てるときの直感とは噛み合いません。「青をちょっと暗くして」と言われたとき、RGB の各チャンネルをどう動かせば「暗く」なるかは、計算しないとわからないですよね。これを解決するのが HSLHSV の 2 つの色空間です。どちらも「色相・彩度・明度」という人間が感じる 3 つの軸で色を指定します。

H(Hue、色相)は 0〜360 度の角度で、色相環のどこにいるかを表します。0 度 = 赤、120 度 = 緑、240 度 = 青、が覚えやすい三原色の位置です。間の黄色・シアン・マゼンタは中間角度にそれぞれ配置されます。色相だけを動かせば「赤を青に寄せる」みたいな操作が 1 軸で済みます。

S(Saturation、彩度)は 0〜100% で、色の鮮やかさです。0% は完全な灰色、100% はその色相のもっとも純粋な色。彩度だけを落とせば「くすませる」ことができ、上げれば「ビビッドにする」ことができます。

L(Lightness、明度)または V(Value、明度)は 0〜100% で、明るさです。ここで HSL と HSV の違いが出てきます。HSL は L = 0 が黒、L = 100 が白、L = 50 がもっとも彩度の効いた純色、という「中央が純色」の設計です。一方の HSV は V = 0 が黒、V = 100 が「そのチャンネルの上限に達した状態」、つまり純色が頂点に来る設計です。

言葉だけだとわかりにくいので感覚的に言うと、HSL は「純色 ↔ 白」「純色 ↔ 黒」の両方向に滑らかに移れる対称的な空間、HSV は「純色 ↔ 黒」の 1 方向だけに整理された円錐です。デザインツールでよく使われているのは HSV のほうで、理由は「明度 V と彩度 S が直交している感覚がつかみやすい」「純色がわかりやすい頂点にある」「カラーピッカーの正方形領域(明度 × 彩度)に自然にマッピングできる」といった実用面にあります。Photoshop・Figma・Sketch などプロ向けツールのピッカーはほぼ全部 HSV ベースです。

CSS では hsl() 関数が使えます(hsv() は CSS では提供されていません)。

/* HSL で青を指定 */
.primary { color: hsl(220, 85%, 55%); }

/* HSL の相対操作: 10% 明るく */
.primary-lighter { color: hsl(220, 85%, 65%); }

/* HSL の相対操作: 彩度を落とす */
.primary-muted { color: hsl(220, 40%, 55%); }

/* アルファ付き(CSS Colors Level 4) */
.primary-overlay { color: hsl(220 85% 55% / 0.6); }

HSV は CSS で直接指定できませんが、HSV → RGB の変換は概念的には次のような手順で行われます。色相から「どの原色の組み合わせか」を決め、彩度で「どれくらい灰色に寄せるか」を調整し、明度で「全体の明るさ」をかける、という 3 ステップです。

// HSV → RGB の概念的な変換
function hsvToRgb(h, s, v) {
  const c = v * s;               // chroma
  const hh = h / 60;             // 0-6 にスケール
  const x = c * (1 - Math.abs(hh % 2 - 1));
  const m = v - c;               // 黒方向の下駄
  let r = 0, g = 0, b = 0;
  if      (hh < 1) [r, g, b] = [c, x, 0];
  else if (hh < 2) [r, g, b] = [x, c, 0];
  else if (hh < 3) [r, g, b] = [0, c, x];
  else if (hh < 4) [r, g, b] = [0, x, c];
  else if (hh < 5) [r, g, b] = [x, 0, c];
  else             [r, g, b] = [c, 0, x];
  return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)];
}

「10% 明るく」「20% 鮮やかに」といった相対操作は、RGB のままだと不可能に近いですが、HSL・HSV なら 1 軸をいじるだけで済みます。デザインから渡ってきた「もう少し明るく」の一言に秒で応えたいなら、HEX を HSL に変換してから調整し、HEX に戻す、というフローが現実的です。

OKLCH と新しい色空間

2020 年代に入ってから Web デザイン界隈で急速に注目を集めているのが OKLCH という色空間です。名前は「OK Lightness Chroma Hue」の略で、2020 年に Björn Ottosson によって発表された Oklab 色空間を「極座標」で表現したバリアントです。CSS Colors Level 4 の一部として 2023 年頃からモダンブラウザに実装が始まり、2025 年以降はプロダクションでも使える選択肢になりました。

OKLCH が画期的なのは「人間の知覚にもとづく均等な明度軸」を持っている点です。従来の HSL は数学的には美しいのですが、人間の目にとっては「hsl(60, 100%, 50%) の黄色」と「hsl(240, 100%, 50%) の青」が同じ「明度 50%」に見えません。実際には黄色のほうがずっと明るく感じます。これは HSL が RGB の機械的な変換に過ぎず、目の感度カーブを考慮していないためです。

OKLCH はこれを根本から改善し、「L 値が同じなら、色相が違っても目に感じる明るさがほぼ同じ」という特性を持ちます。ダーク/ライトテーマを切り替えるとき、ボタンやテキストの「明度」を揃えたいデザインシステムにとってこれは福音です。HSL でダークテーマを作ると、色相ごとに明度を手で調整しないと不揃いに見えますが、OKLCH なら「全部 L = 0.65」と指定するだけでバランスが取れます。

/* OKLCH で指定 */
.primary    { color: oklch(0.65 0.18 260); }  /* 青系 */
.success    { color: oklch(0.65 0.18 150); }  /* 緑系 */
.danger     { color: oklch(0.65 0.18 25);  }  /* 赤系 */
/* ↑ 3 色とも L = 0.65、Chroma = 0.18 で揃っているので、
   視覚的にほぼ同じ明るさ・鮮やかさに見える */

もうひとつ OKLCH のおいしいところは、広色域への対応です。sRGB の範囲を超えた色も一貫した表現で指定でき、Display P3 のような広い色空間でも「同じ L なら同じ明るさ」の法則が保たれます。未来を見据えるなら OKLCH で書いておき、sRGB のフォールバックを併記する、というのが 2026 年現在のベストプラクティスです。

/* フォールバック付きで OKLCH を使う */
.primary {
  color: #2563eb;                          /* 古いブラウザ向け */
  color: oklch(0.55 0.20 260);             /* 新しいブラウザ向け */
}

color-mix() で色を混ぜる」「color() で任意の色空間を指定する」といった新機能も OKLCH と一緒に使うと威力を発揮します。デザインシステムを一からやり直す予定があるなら、OKLCH 前提で設計してみる価値は十分にあります。

CSS 変数でテーマ化

色を直接ハードコードする時代はもう終わりました。モダンな CSS では カスタムプロパティ(CSS 変数)を使ってテーマカラーを 1 箇所に集約し、ダーク/ライトや複数ブランドの切り替えを簡単にするのが定石です。基本形は :root に変数を定義し、各コンポーネントから var() で参照するだけ。

:root {
  --bg:       #ffffff;
  --fg:       #111827;
  --primary:  #2563eb;
  --muted:    #6b7280;
  --accent:   #f59e0b;
  --border:   #e5e7eb;
}

body {
  background: var(--bg);
  color: var(--fg);
}

.button {
  background: var(--primary);
  color: #fff;
}

ダークテーマを切り替えるには、メディアクエリやクラスを使って変数の値を上書きするだけです。コンポーネント側の CSS は一切触らなくて済むので、あとからテーマを追加するときも影響範囲が最小になります。

/* システム設定に応じて自動切り替え */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:       #0b1120;
    --fg:       #f3f4f6;
    --primary:  #60a5fa;
    --muted:    #9ca3af;
    --accent:   #fbbf24;
    --border:   #1f2937;
  }
}

/* ユーザー操作で切り替える場合 */
[data-theme="dark"] {
  --bg:       #0b1120;
  --fg:       #f3f4f6;
  /* ... */
}

2025 年頃から本格的に使えるようになったのが color-mix() 関数です。「この色と白を 80 対 20 で混ぜた色が欲しい」という操作が CSS の中で完結できます。OKLCH 空間で混色することで、視覚的に滑らかなバリエーションを作れるのが嬉しいポイント。

:root {
  --primary:        #2563eb;
  --primary-soft:   color-mix(in oklch, var(--primary) 80%, white);
  --primary-strong: color-mix(in oklch, var(--primary) 80%, black);
  --primary-10:     color-mix(in oklch, var(--primary) 10%, transparent);
}

アルファ値も変数と組み合わせて扱えます。古い書き方だと「同じ色の不透明度違い」を複数の変数で管理していましたが、color-mix と相対色記法のおかげで 1 つの基準色から派生色を自動生成できます。デザインシステムが軽量化する方向への大きな変化です。

/* 相対色記法で同じベースからバリエーションを作る */
:root { --primary: oklch(0.55 0.20 260); }
.card {
  background: rgb(from var(--primary) r g b / 0.08);
  border: 1px solid rgb(from var(--primary) r g b / 0.2);
  color: var(--primary);
}

CSS 変数は JavaScript から読み書きもできるので、「ユーザーがピッカーで選んだ色をリアルタイムで反映する」ような動的なテーマ化も簡単です。document.documentElement.style.setProperty('--primary', userColor) と 1 行書けば全コンポーネントが即座に追従します。

カラーピッカーの選び方

カラーピッカーと一口に言っても、UI の設計は大きく 2 系統に分かれます。ひとつは RGB スライダー型で、R・G・B の 3 本のスライダーを並べた古典的なタイプ。もうひとつは HSV サークル(リング)型で、色相を円環で選び、内側の正方形で彩度と明度を指定するタイプ。どちらを選ぶかで作業効率が大きく変わります。

RGB スライダー型は、マシンの内部表現そのままなので「この色を他のシステムに渡すときの値を確認したい」ときには向いています。ただし、色を「作る」作業には向きません。「今選んでいる赤をもう少し明るくしたい」と思っても、R だけを足すのか、G と B も一緒に足すのか、判断がつかないからです。結果的に「スライダー 3 本をちまちま動かしながら試行錯誤する」ことになり、プロのデザイナにとってはストレスの溜まる UI になります。

HSV サークル型は、3 つの軸がそれぞれ独立した操作感を持つのが強みです。色相リングで「どの色系統か」を決め、正方形の中で「鮮やかさと明るさ」を調整する、という分業が直感的。たとえば「青系のベースカラーを決めた後、そこから数段階の明るさバリエーションを作りたい」ときは、正方形の上下を動かすだけで連続的に明度を変えられます。Photoshop・Figma・Illustrator など、プロ向けツールのピッカーがほぼ全部この系統なのは偶然ではなく、作業効率が段違いだからです。

Web のブラウザ標準である <input type="color"> は OS のネイティブピッカーを呼び出します。macOS なら Apple 純正のカラーパネル(HSV・HSL・RGB・鉛筆・クレヨンなど複数の UI が切り替えられる優秀なもの)、Windows や Linux ではシンプルな四角形ピッカーが出てきます。OS のばらつきを避けたい、あるいは「正確な HEX コードをコピペしたい」ときは、Web ベースのカスタムピッカーや外部ツールを使うのが実用的です。

ベンリーの HSV カラーピッカー は、HSV の正方形 + 色相リングというプロ向けの UI を Web 上で再現しており、HEX・RGB・HSL・HSV のすべてで値をリアルタイム表示します。ブラウザ標準のピッカーに不満があるときの代替として、またデザインツールを開くほどでもない軽い作業のときに重宝します。

パレット設計

Web サイトやアプリのデザインを組むとき、色を 1 つだけ決めて終わり、というケースはまずありません。「プライマリ・セカンダリ・アクセント・状態色」くらいは最低限そろえ、それぞれに明度バリエーション(10 段階など)を用意するのが現代のデザインシステムの常識です。これを構造化したものが カラーパレットです。

一般的な役割分担は次のとおりです。

  • プライマリ(primary / brand): ブランドを代表するメインカラー。ボタン・リンク・強調したい箇所に使う。
  • セカンダリ(secondary): プライマリを補助する色。ナビゲーションや二次的な UI 要素に使う。
  • アクセント(accent): 「ここに目を向けてほしい」場所に差す色。通知バッジ・お知らせ・セール表示など。
  • ニュートラル(neutral / gray): 背景・テキスト・ボーダーに使う無彩色のスケール。デザインの 80% はここで占められる。
  • セマンティックカラー(状態色): success(成功)・warning(警告)・danger(エラー)・info(情報)。ユーザーに状態を伝える役割。

それぞれを 1 色だけ決めるのではなく、明度のスケールを持たせるのが実務の定番です。Tailwind CSS は 50 / 100 / 200 / ... / 900 / 950 の 11 段階、Material Design は 50 / 100 / 200 / ... / 900 / A100 / A200 / A400 / A700 といった段階分けを採用しています。スケールが揃っていれば「背景は 50、ボーダーは 200、テキストは 700」のような一貫したルールで UI を組めます。

/* Tailwind 風の blue スケール(抜粋) */
:root {
  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-200: #bfdbfe;
  --blue-300: #93c5fd;
  --blue-400: #60a5fa;
  --blue-500: #3b82f6; /* ベース */
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;
  --blue-800: #1e40af;
  --blue-900: #1e3a8a;
}

OKLCH を使うと、このスケール生成がぐっと楽になります。色相を固定して L だけを 0.95 → 0.15 まで刻むと、視覚的に均等な明度のスケールが一発で作れます。Tailwind も v4 から内部表現が OKLCH に切り替わりました。

パレット設計の TL;DR

プライマリ 1 色を決めたら、色相を固定して明度スケールを 9〜11 段階作る。状態色(success / warning / danger / info)は別系統の色相で同じスケールを展開する。ニュートラルはわずかにプライマリの色相に寄せた「ウォームグレー」または「クールグレー」にすると全体に統一感が出る。OKLCH で L を等間隔に刻めば視覚的に均等なスケールになります。迷ったら Tailwind v4 の blueslate を開いて見比べるのが最短です。

パレットができたら、Figma や Sketch の「スタイル」として登録し、エンジニア側は CSS 変数や Tailwind の設定ファイルに落とす、という流れで二重管理を防げます。デザイナとエンジニアが「同じ名前で同じ色を指す」状態を維持できるかが、デザインシステム運用の 9 割です。

コントラスト比(WCAG AA/AAA)

色をきれいに組んだあと必ずチェックすべきなのが コントラスト比です。背景とテキストの明暗差が足りないと、ロービジョンや加齢による視力低下のあるユーザーに読めなくなります。これを数値で管理するための指標が、WCAG 2.1(Web Content Accessibility Guidelines)の コントラスト比です。

計算は「背景とテキストの相対輝度(relative luminance)を求め、明るいほうを暗いほうで割る」というもの。結果は 1:1(同じ色)から 21:1(黒と白)までの範囲に収まります。WCAG 2.1 は次の 3 段階の基準を設けています。

テキストサイズAA(必須レベル)AAA(推奨レベル)
通常テキスト(14px 未満)4.5:1 以上7:1 以上
大きなテキスト(18px 以上、または 14px 太字)3:1 以上4.5:1 以上
UI コンポーネント・グラフィカル要素3:1 以上

AA の 4.5:1」が事実上の業界標準で、政府機関・金融・医療・教育などアクセシビリティ要件がある業界では必須と考えたほうがいいです。一般向けの Web サービスでも、最低限 AA は満たすのが 2026 年のスタンダード。AAA は厳しめで、装飾的な見出しやヒーローコピーだけでクリアするのは難しいので、ボディテキストで目指すのが現実的です。

相対輝度の計算式は sRGB の各チャンネルをガンマ補正した後、重み付けして足すという少し複雑なものですが、ライブラリや Web ツールを使えば一瞬で出せます。主要な CSS のエディタ拡張(Stylelint の a11y プラグイン、VS Code の Color Highlight など)にもコントラスト比チェック機能があるので、コードを書きながらリアルタイムに確認できます。

// 相対輝度の概念実装(簡略版)
function luminance(r, g, b) {
  const srgb = [r, g, b].map(v => {
    const x = v / 255;
    return x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
  });
  return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
}

function contrast(rgb1, rgb2) {
  const L1 = luminance(...rgb1);
  const L2 = luminance(...rgb2);
  const [lighter, darker] = L1 > L2 ? [L1, L2] : [L2, L1];
  return (lighter + 0.05) / (darker + 0.05);
}

contrast([37, 99, 235], [255, 255, 255]); // → 5.17(AA 通過)

WCAG 2.1 の計算式は 1999 年の古い実験データに基づいており、実は細部で現実と合わない部分があります。特に「明るいグレーの上の白文字」のようなケースで、数式上はコントラスト比が十分でも実際には読みづらい、といった現象が知られています。これを改善した次世代指標が APCA(Advanced Perceptual Contrast Algorithm)で、WCAG 3.0 の草案に組み込まれる予定です。2026 年時点ではまだ正式採用には至っていませんが、Apple や一部のデザインシステムは既に APCA を採用しています。今後の動向を追っておく価値があります。

アクセシビリティとカラーブラインド

コントラスト比と並んで、色の設計で見落とされがちなのが カラーブラインド(色覚特性)への配慮です。日本人男性の約 5%、女性の約 0.2%、世界全体では男性約 8% に何らかの色覚特性があると言われています。日本の男子校 1 クラス 40 人に 2 人はいる計算で、Web サービスのユーザーベースが数万人を超えるなら無視できない数字です。

主なタイプは次のとおりです。

  • 1 型(赤色覚異常、protanopia): 赤の感度が低く、赤と緑の区別がつきにくい。赤信号が暗く見える。
  • 2 型(緑色覚異常、deuteranopia): 緑の感度が低い。1 型に似た見え方だが、暗くなる方向が逆。日本でもっとも多いタイプ。
  • 3 型(青色覚異常、tritanopia): 青と黄の区別がつきにくい。1・2 型より頻度は低い。

実務でもっとも問題になるのは「赤と緑の区別」です。グラフで「売上増 = 緑、売上減 = 赤」のように色だけで意味を伝えると、1・2 型の人には同じ色に見えてしまい、情報が失われます。フォームのエラー表示も「赤い枠線だけ」だと気づかれないケースがあるので要注意です。

色だけで情報を伝えてはいけない

WCAG 2.1 の達成基準 1.4.1 は「色の使用」を定めており、色だけを使って情報・操作・反応を伝えてはならないとしています。実務では「色 + テキストラベル」「色 + アイコン」「色 + パターン/形」のように、色以外の手段を必ず併用するのが鉄則です。グラフなら凡例の色に加えて形(丸・四角・三角)や文字を付ける、フォームのエラーなら赤い枠線に加えてエラーアイコンとエラーメッセージを出す、といった配慮が必要です。

実際にどう見えるかを確認するには、シミュレーションツールが便利です。macOS なら「ディスプレイのカラーフィルタ」機能で色覚特性を疑似体験できますし、Chrome DevTools の Rendering パネルには「Emulate vision deficiencies」があり、blurred vision・protanopia・deuteranopia・tritanopia・achromatopsia を即座に切り替えて確認できます。デザインレビューのときに必ず一度は通しておきたい工程です。

パレットの段階で「色覚特性のある人にも区別できるか」を考慮したい場合は、色相をできるだけ離すのが基本戦略です。赤と緑を隣接させず、青と黄のように知覚的に遠い色相を使う。どうしても赤と緑を近接させる必要があるなら、明度を大きく変える(濃い赤 + 淡い緑)ことで 1・2 型の人でも区別できるようにします。OKLCH の L 軸を揃えすぎないのがコツです。

ベンリーの 3 ツール使い分け

ベンリーには色周りのツールが 3 つあります。それぞれ得意分野が違うので、用途に合わせて選んでください。

ツール用途こんなときに
カラーコンバータHEX ⇔ RGB ⇔ HSL ⇔ HSV 変換Figma で見た HEX を CSS の hsl() に変換したい、デザイナから渡された色を別フォーマットで確認したい、rgba() のアルファ値を別の HEX で書き直したい、などのフォーマット変換作業全般。
HSV カラーピッカープロ仕様のビジュアルな色選び新しい色を「作りたい」ときの本命。色相リング + 明度彩度の正方形という Photoshop 系 UI で、HSV を直感的に操作しながら HEX や RGB の値をその場で確認できる。パレットのベースカラーを決める作業に最適。
CSS パレットテスター作ったパレットをコンポーネント上で確認パレットが決まった後、実際のボタンやカードや本文の上でどう見えるかをその場で試せるツール。コントラスト比の自動判定付きで、WCAG AA/AAA の達成状況も即座にわかる。デザインシステム検証の最終確認に。

おすすめの流れはこうです。まず HSV カラーピッカーでベースカラーを選び、得られた HEX を カラーコンバータで別の表記(HSL や OKLCH)に変換してバリエーションを手でいじり、最後に CSS パレットテスターで全体を並べて見比べながらコントラスト比を確認する。3 ツールが連携することでデザインシステムの最小セットを 15 分で作れます。

よくある質問

#FFF#FFFFFF は同じ?

はい、まったく同じ色(純白)です。CSS の HEX 記法では 3 桁形式は 6 桁形式のシンタックスシュガーで、各チャンネルの 1 桁を 2 回繰り返した値として解釈されます。#FFF#FFFFFF#F0A#FF00AA という具合です。ただし表現できる色は 4096 色に限定される(各チャンネルが 16 階調だけになる)ので、#1A2B3C のような細かい調整が必要な色は 6 桁で書く必要があります。短縮形は本文中で色をサクッと書きたいときや、純色に近い色を指定するときに便利です。

なぜ HSV はデザイナに人気?

3 つの軸(色相・彩度・明度)が人間の感覚にマッチしていて、かつ直交性が高いからです。「鮮やかさだけ上げたい」「明るさだけ落としたい」といった操作が、1 本のスライダーを動かすだけで完結します。RGB だと同じ操作に 3 つの値を微調整しなくてはならず、試行錯誤のコストが段違いです。また HSV は「純色が頂点(V = 100、S = 100)にある」構造で、カラーピッカーの正方形領域と素直にマッピングできるため、Photoshop や Figma のピッカー UI が全部 HSV を採用しています。数学的な対称性では HSL のほうがきれいですが、作業効率では HSV に軍配が上がる、というのがプロの現場の選び方です。

RGB を「明るく」したいときはどうする?

RGB の 3 値をそのまま同じ量だけ足せば明るくなりますが、彩度が落ちて白っぽくなるので「色味を保ったまま明るくする」には向きません。もっとも確実なのは、いったん HSL または HSV に変換して L(あるいは V)だけを増やし、結果を RGB に戻す方法です。CSS なら最初から hsl() で書いておけば L の数値を大きくするだけで済みます。現代的な方法としては color-mix(in oklch, var(--primary) 80%, white) のように OKLCH 空間で白と混ぜるやり方もあり、色相のブレが最小になるのでおすすめです。

OKLCH を使うメリットは?

いちばん大きいのは「L 値が同じなら、色相が違っても人間の目に同じ明るさに感じる」という知覚均等性です。HSL だと hsl(60, 100%, 50%) の黄色と hsl(240, 100%, 50%) の青は、数値上は同じ明度ですが実際には黄色のほうが圧倒的に明るく見えます。OKLCH ではこれが揃うので、ダーク/ライトテーマや状態色のバランスが取りやすくなります。もうひとつの利点は広色域対応で、sRGB の枠を超えた色(Display P3 など)も同じ感覚で指定できます。デメリットとしては 2023 年より前のブラウザでは使えないので、プロダクションではフォールバック付きで使うのが無難です。

コントラスト比 4.5:1 はなぜ必要?

WCAG 2.1 の AA 基準で定められている数値で、視力 20/40(小数で 0.5、一般的な老眼の入り口くらい)の人がロービジョン補助を使わずにテキストを読めるラインとして設計されています。ロービジョンや色覚特性、加齢による視力低下を持つユーザーが全人口の 10〜15% 程度いることを考えると、どんな Web サービスでも無視できる数字ではありません。公共サービスや医療・金融のように「読めないことが直接的な不利益につながる」分野では AA の遵守が法的にも求められる国・地域が増えています(EU の European Accessibility Act など)。デザインの段階で必ずコントラスト比をチェックする習慣をつけておくと、後から修正のコストが大幅に下がります。

カラーコードをその場で試したいなら

ベンリーには色周りのツールが 3 つそろっています。新しい色を作るなら HSV カラーピッカー、フォーマット変換ならカラーコンバータ、パレットをコンポーネント上で確認したいなら CSS パレットテスター。どれもブラウザ内で完結するので、デザインファイルを開くほどでもない軽い作業に最適です。

カラーコンバータを開く →