デザインシステムの構築、CSSのデバッグ、モックアップのコード変換など、信頼性の高いカラーコンバーターは開発者ツールキットで最も使用されるツールの一つです。本ガイドでは主要なカラーモデル、変換の数学的原理、JavaScript/Python/Bashのコード例、oklch()やcolor-mix()などの最新CSS機能を網羅します。
カラーモデルの理解:RGB、HEX、HSL、HSV、CMYK
RGB(赤、緑、青)はスクリーン表示の基本カラーモデルです。各ピクセルは0-255の強度で赤、緑、青の光を混合します。RGBは加法混色モデルで、3チャネル最大値で白になります。
HEX(16進数)はWebで最も一般的なカラー表記です。RGB値を16進数で表現したもので、#FF5733はrgb(255, 87, 51)と同じです。3桁、6桁、8桁形式があります。
HSL(色相、彩度、明度)はより直感的に設計されています。色相は色相環上の角度(0-360)、彩度と明度はパーセンテージです。HSLは明暗バリエーションの作成を簡単にします。
HSV/HSB(色相、彩度、明度値)はPhotoshopやFigmaなど多くのカラーピッカーで使用されるモデルです。CSSはHSVを直接サポートしていません。
CMYK(シアン、マゼンタ、イエロー、ブラック)は印刷用の減法混色モデルです。PDF生成や印刷ファイル準備に不可欠です。
カラーモデル比較表
以下の表は各カラーモデルの主要な特性をまとめています:
| Model | Format | Range | Use Case | CSS Support | Human-Readable |
|---|---|---|---|---|---|
| RGB | rgb(R, G, B) | 0-255 per channel | Screen display, Canvas, WebGL | Yes | Low |
| HEX | #RRGGBB | 00-FF per channel | CSS, design tools, tokens | Yes | Low |
| HSL | hsl(H, S%, L%) | H: 0-360, S/L: 0-100% | Theming, shade generation | Yes | High |
| HSV/HSB | hsv(H, S%, V%) | H: 0-360, S/V: 0-100% | Color pickers (Photoshop, Figma) | No | High |
| CMYK | cmyk(C%, M%, Y%, K%) | 0-100% per channel | Print, PDF generation | No | Medium |
| OKLCH | oklch(L C H) | L: 0-1, C: 0-0.4, H: 0-360 | Modern CSS, wide gamut | Yes | High |
カラー変換の仕組み
すべてのカラーコンバーターは既知の数学的公式を実装しています。これらの公式を理解することでエッジケースのデバッグに役立ちます。
HEX→RGB:#FF5733のような16進カラーコードは3つの16進ペアで構成されます。各ペアを独立して解析しRGB値を取得します。
RGB→HEX:各チャネル値(0-255)を2桁の16進文字列に変換し、#プレフィックスで連結します。
RGB→HSL:R、G、Bを0-1に正規化し、Cmax、Cminを求め、デルタ、明度、彩度、色相を計算します。
HSL→HEX:まずHSLをRGBに変換し、各RGBチャネルを16進数に変換します。
RGB→HSV:色相計算はRGB→HSLと同じです。V = Cmax、S = delta / Cmax。
HSL⇔HSV:両方とも色相を共有しますが、彩度と明度/値の変換には特定の公式が必要です。
カラー変換コード例
JavaScript / CSS カラー変換
JavaScriptには組み込みカラーコンバーターがありませんが、CSSカラー関数で変換は簡単です:
// ===== HEX to RGB =====
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
hexToRgb('#FF5733'); // { r: 255, g: 87, b: 51 }
// ===== RGB to HEX =====
function rgbToHex(r, g, b) {
return '#' + [r, g, b]
.map(x => x.toString(16).padStart(2, '0'))
.join('');
}
rgbToHex(255, 87, 51); // "#ff5733"
// ===== RGB to 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);
const l = (max + min) / 2;
if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };
const d = max - min;
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
let h = 0;
switch (max) {
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
case g: h = ((b - r) / d + 2) / 6; break;
case b: h = ((r - g) / d + 4) / 6; break;
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100)
};
}
rgbToHsl(255, 87, 51); // { h: 11, s: 100, l: 60 }
// ===== HSL to RGB =====
function hslToRgb(h, s, l) {
s /= 100; l /= 100;
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
const m = l - c / 2;
let r = 0, g = 0, b = 0;
if (h < 60) { r = c; g = x; b = 0; }
else if (h < 120) { r = x; g = c; b = 0; }
else if (h < 180) { r = 0; g = c; b = x; }
else if (h < 240) { r = 0; g = x; b = c; }
else if (h < 300) { r = x; g = 0; b = c; }
else { r = c; g = 0; b = x; }
return {
r: Math.round((r + m) * 255),
g: Math.round((g + m) * 255),
b: Math.round((b + m) * 255)
};
}
hslToRgb(11, 100, 60); // { r: 255, g: 87, b: 51 }
// ===== CSS native color parsing (modern browsers) =====
// Use CSS.supports() and getComputedStyle for runtime conversion
const el = document.createElement('div');
el.style.color = 'hsl(14 100% 60%)';
document.body.appendChild(el);
const rgb = getComputedStyle(el).color;
// "rgb(255, 87, 51)" - browser converts any format to RGB
document.body.removeChild(el);Python カラー変換
PythonはcolorsysモジュールでHSL/HSV変換を提供し、Pillowやmatplotlibも利用できます:
import colorsys
# ===== RGB to HSL (colorsys uses HLS order) =====
r, g, b = 255, 87, 51
r_norm, g_norm, b_norm = r / 255, g / 255, b / 255
h, l, s = colorsys.rgb_to_hls(r_norm, g_norm, b_norm)
print(f"HSL: ({h*360:.0f}, {s*100:.0f}%, {l*100:.0f}%)")
# HSL: (11, 100%, 60%)
# ===== HSL to RGB =====
r2, g2, b2 = colorsys.hls_to_rgb(h, l, s)
print(f"RGB: ({r2*255:.0f}, {g2*255:.0f}, {b2*255:.0f})")
# RGB: (255, 87, 51)
# ===== RGB to HSV =====
h_hsv, s_hsv, v_hsv = colorsys.rgb_to_hsv(r_norm, g_norm, b_norm)
print(f"HSV: ({h_hsv*360:.0f}, {s_hsv*100:.0f}%, {v_hsv*100:.0f}%)")
# HSV: (11, 80%, 100%)
# ===== HEX to RGB =====
def hex_to_rgb(hex_color):
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
print(hex_to_rgb("#FF5733")) # (255, 87, 51)
# ===== RGB to HEX =====
def rgb_to_hex(r, g, b):
return f"#{r:02x}{g:02x}{b:02x}"
print(rgb_to_hex(255, 87, 51)) # #ff5733
# ===== Using matplotlib colors =====
import matplotlib.colors as mcolors
rgb_tuple = mcolors.to_rgb('#FF5733') # (1.0, 0.341, 0.2)
hex_value = mcolors.to_hex((1.0, 0.341, 0.2)) # '#ff5733'
rgba = mcolors.to_rgba('steelblue', alpha=0.5)
# ===== Using Pillow/PIL for image colors =====
from PIL import Image
img = Image.new('RGB', (1, 1), (255, 87, 51))
pixel = img.getpixel((0, 0)) # (255, 87, 51)
img_hsv = img.convert('HSV') # Convert to HSV color spaceBash / CLI カラー変換
printfやImageMagickなどのコマンドラインツールで基本的なカラー変換が可能です:
# ===== HEX to RGB using printf =====
hex="FF5733"
printf "RGB: %d, %d, %d\n" 0x${hex:0:2} 0x${hex:2:2} 0x${hex:4:2}
# RGB: 255, 87, 51
# ===== RGB to HEX using printf =====
r=255 g=87 b=51
printf "#%02x%02x%02x\n" $r $g $b
# #ff5733
# ===== ImageMagick color conversion =====
# Convert HEX to RGB
magick convert xc:"#FF5733" -format "%[fx:int(255*r)],%[fx:int(255*g)],%[fx:int(255*b)]" info:
# 255,87,51
# Get color info in multiple formats
magick convert xc:"#FF5733" -colorspace HSL -format "HSL: %[fx:r*360],%[fx:g*100]%%,%[fx:b*100]%%" info:
# ===== Convert named color to HEX =====
magick convert xc:"tomato" -format "#%02[hex:r]%02[hex:g]%02[hex:b]" info:
# #FF6347
# ===== Batch convert colors from file =====
# colors.txt: one hex color per line
while IFS= read -r color; do
printf "%s -> RGB: %d, %d, %d\n" "$color" \
0x${color:1:2} 0x${color:3:2} 0x${color:5:2}
done < colors.txtモダンCSSカラー機能
モダンCSSは知覚的に均一な色空間、広色域カラー、強力な色操作関数をサポートしています:
/* ===== Modern CSS color syntax (no commas) ===== */
.element {
/* RGB - modern space-separated */
color: rgb(255 87 51);
color: rgb(255 87 51 / 0.5); /* with alpha */
/* HSL - modern space-separated */
background: hsl(14 100% 60%);
background: hsl(14 100% 60% / 0.8);
/* HWB - Hue, Whiteness, Blackness */
border-color: hwb(14 0% 0%); /* pure orange */
border-color: hwb(14 20% 10%); /* muted orange */
}
/* ===== OKLCH - perceptually uniform ===== */
.brand {
--brand-primary: oklch(0.65 0.25 29); /* vivid red-orange */
--brand-light: oklch(0.85 0.12 29); /* light variant */
--brand-dark: oklch(0.45 0.20 29); /* dark variant */
/* Same hue, predictable lightness changes */
}
/* ===== color-mix() - blend colors ===== */
.mixed {
background: color-mix(in oklch, #FF5733 70%, #3366FF);
border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
}
/* ===== Relative color syntax ===== */
.derived {
--base: #FF5733;
/* Lighten by increasing L in oklch */
color: oklch(from var(--base) calc(l + 0.2) c h);
/* Desaturate by reducing chroma */
background: oklch(from var(--base) l calc(c * 0.5) h);
/* Shift hue by 180 degrees (complementary) */
border-color: hsl(from var(--base) calc(h + 180) s l);
}
/* ===== Wide gamut P3 colors ===== */
@supports (color: color(display-p3 1 0 0)) {
.vivid {
color: color(display-p3 1 0.3 0.1); /* more vivid than sRGB */
}
}
/* ===== Dark mode with light-dark() ===== */
:root {
color-scheme: light dark;
--text: light-dark(#1a1a1a, #e5e5e5);
--surface: light-dark(#ffffff, #121212);
}
/* ===== CSS custom properties for theming ===== */
:root {
--color-primary-h: 14;
--color-primary-s: 100%;
--color-primary-l: 60%;
--color-primary: hsl(
var(--color-primary-h)
var(--color-primary-s)
var(--color-primary-l)
);
--color-primary-hover: hsl(
var(--color-primary-h)
var(--color-primary-s)
calc(var(--color-primary-l) - 10%)
);
}CSSカラー関数の詳細
モダンCSSは豊富なカラー関数を提供します。rgb()はスペース区切り構文を受け入れます。hwb()(色相、白度、黒度)はより直感的な代替手段です。
oklch()はWebカラーのブレークスルーです。Oklab色空間に基づき、同じ明度の色が実際に同じ明るさに見えることを保証します。P3広色域も利用可能になります。
color-mix()は任意の色空間で2色を混合します。相対カラー構文で既存の色から新しい色を導出できます。
その他の便利な値:currentColor、transparent、テーマ用CSSカスタムプロパティ、light-dark()による自動カラースキーム選択。
カラーアクセシビリティとコントラスト
WCAGコントラスト比はアクセシブルなカラーデザインの基盤です。AAは通常テスト4.5:1、大きなテキスト3:1を要求。AAAは7:1と4.5:1を要求します。
男性の約8%に何らかの色覚異常があります。情報伝達を色だけに頼らないでください。赤/緑、青/紫の組み合わせを避けましょう。
OKLCHを使用して知覚的に均一な色調生成でアクセシブルなパレットを構築します。すべての前景/背景の組み合わせをテストしましょう。
開発者のためのカラーベストプラクティス
パレットをデザイントークンとして定義し、CSSカスタムプロパティにマッピングします。--color-text-primaryのようなセマンティック名を使用しましょう。
ダークモードは単純な明度反転ではなく、独自のパレットを持つ別テーマとして設計します。
コンポーネントスタイルで生のHEXやRGB値を直接使用しないでください。常にトークンを参照します。
アニメーションではoklch()補間を使用してよりスムーズな知覚的遷移を実現します。
よくある質問
HEXとRGBの相互変換方法は?
HEX→RGB:コードを3ペアに分割し、各ペアを16進整数として解析します。RGB→HEX:各チャネルを2桁のHEX文字列に変換し連結します。オンラインツールで即座に変換できます。
Web開発に最適なカラー形式は?
HEXがほとんどのプロジェクトでデフォルトです。HSLはテーマ設定に適しています。最新ブラウザではoklch()が知覚的に均一な色とP3色域で最良の選択です。
WCAGのカラーコントラスト要件は?
AAは通常テキスト4.5:1、大きなテキスト3:1を要求。AAAは7:1と4.5:1。非テキスト要素は最低3:1が必要です。常にコントラストチェッカーでテストしましょう。
カラー変換はデザインツール、CSS、アクセシビリティ、バックエンド処理をつなぐ基本スキルです。無料ツールで即座に変換できます。