mcpField
C
color-palette

color-palette

github.com/jezwebデザイン・UI1.1k3.3k 回インストール3 週間前に更新
リポジトリ

color-palette について

1 色のブランドカラーから、セマンティックトークンとライト・ダークモードの設定を含む Tailwind v4 の配色システムを作るスキルです。コントラスト確認とアクセシビリティ向けの調整も扱います。

主な機能

  1. 0111 段階のカラースケール生成
  2. 02シェードをセマンティックトークンに対応付け
  3. 03ライト・ダークモードの色ペア設定
  4. 04WCAG コントラスト比の確認
  5. 05Tailwind v4 CSS の出力

活用シーン

  1. 01ブランドカラーからテーマを作成
  2. 02背景と前景のトークンをペアで設定
  3. 03両モードでテキストと UI のコントラストを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jezweb/claude-skills --skill color-palette

インストール後、Claude Code で/color-paletteを入力して読み込まれたか確認します。

同梱ファイルassets/tailwind-colors.css

詳細

カラーパレットジェネレーター

1つのブランドカラーの16進数コードから、アクセシビリティに配慮した完全なカラーシステムを生成します。プロジェクトにそのまま貼り付けられる Tailwind v4 CSS を出力します。

ワークフロー

ステップ 1:ブランドカラーの16進数コードを取得する

メインのブランドカラーを尋ねます。#0D9488 のような16進数コード1つで十分です。

ステップ 2:11段階のスケールを生成する

16進数コードを HSL に変換し、色相を固定したまま明度を変えて各シェードを生成します。

16進数コードから HSL への変換
function hexToHSL(hex) {
  hex = hex.replace(/^#/, '');
  const r = parseInt(hex.substring(0, 2), 16) / 255;
  const g = parseInt(hex.substring(2, 4), 16) / 255;
  const b = parseInt(hex.substring(4, 6), 16) / 255;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const diff = max - min;

  let l = (max + min) / 2;
  let s = 0;
  if (diff !== 0) {
    s = l > 0.5 ? diff / (2 - max - min) : diff / (max + min);
  }

  let h = 0;
  if (diff !== 0) {
    if (max === r) h = ((g - b) / diff + (g < b ? 6 : 0)) / 6;
    else if (max === g) h = ((b - r) / diff + 2) / 6;
    else h = ((r - g) / diff + 4) / 6;
  }

  return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
}
明度と彩度の値
シェード明度彩度の倍率用途
5097%0.80控えめな背景
10094%0.80ホバー状態
20087%0.85境界線、区切り線
30075%0.90無効状態
40062%0.95プレースホルダーテキスト
50048%1.00ブランドカラーの基準
60040%1.00主要なアクション(多くの場合、ブランドカラー)
70033%1.00主要な要素のホバー状態
80027%1.00アクティブ状態
90020%1.00明るい背景上のテキスト
95010%1.00最も暗いアクセント

明るいシェード(50~200)は彩度を15~20%、300~400は5~10%下げて、パステルカラーが鮮やかになりすぎないようにします。500~950は彩度を最大に保ちます。

スケール全体の生成
function generateShadeScale(brandHex) {
  const { h, s } = hexToHSL(brandHex);
  const shades = {
    50:  { l: 97, sMul: 0.8 },  100: { l: 94, sMul: 0.8 },
    200: { l: 87, sMul: 0.85 }, 300: { l: 75, sMul: 0.9 },
    400: { l: 62, sMul: 0.95 }, 500: { l: 48, sMul: 1.0 },
    600: { l: 40, sMul: 1.0 },  700: { l: 33, sMul: 1.0 },
    800: { l: 27, sMul: 1.0 },  900: { l: 20, sMul: 1.0 },
    950: { l: 10, sMul: 1.0 }
  };
  const result = {};
  for (const [shade, { l, sMul }] of Object.entries(shades)) {
    result[shade] = `hsl(${h}, ${Math.round(s * sMul)}%, ${l}%)`;
  }
  return result;
}
HSL から16進数コードへの変換
function hslToHex(h, s, l) {
  s = s / 100; l = 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; }
  else if (h < 120) { r = x; g = c; }
  else if (h < 180) { g = c; b = x; }
  else if (h < 240) { g = x; b = c; }
  else if (h < 300) { r = x; b = c; }
  else { r = c; b = x; }
  r = Math.round((r + m) * 255);
  g = Math.round((g + m) * 255);
  b = Math.round((b + m) * 255);
  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toUpperCase();
}
検証

生成されたシェードが同じ色の系統に見え、滑らかに変化していることを確認します。明るいシェード(50~300)は背景に、暗いシェード(700~950)はテキストに使用できます。ブランドカラーは500~700で認識できる状態にします。


ステップ 3:セマンティックトークンを割り当てる

背景トークンには必ず対応する前景トークンを設定します。対応するトークンなしで背景を使用しないでください。ダークモードが正しく機能しなくなります。

ライトモードのトークン
トークンシェード用途
background白ページの背景
foreground950本文テキスト
card白カードの背景
card-foreground900カードのテキスト
popover白ドロップダウン/ツールチップの背景
popover-foreground950ドロップダウンのテキスト
primary600主要なボタン、リンク
primary-foreground白主要なボタン上のテキスト
secondary100セカンダリボタン
secondary-foreground900セカンダリボタン上のテキスト
muted50無効状態の背景、控えめなセクション
muted-foreground600控えめなテキスト、キャプション
accent100ホバー状態、控えめな強調表示
accent-foreground900アクセント背景上のテキスト
destructivered-600削除ボタン、エラー
destructive-foreground白削除ボタン上のテキスト
border200入力欄の境界線、区切り線
input200入力フィールドの境界線
ring600フォーカスリング
ダークモードのトークン
トークンシェード用途
background950ページの背景
foreground50本文テキスト
card900カードの背景
card-foreground50カードのテキスト
popover900ドロップダウンの背景
popover-foreground50ドロップダウンのテキスト
primary500主要なボタン(ダークモードでは明るめ)
primary-foreground白主要なボタン上のテキスト
secondary800セカンダリボタン
secondary-foreground50セカンダリボタン上のテキスト
muted800無効状態の背景
muted-foreground400控えめなテキスト
accent800ホバー状態
accent-foreground50アクセント背景上のテキスト
destructivered-500削除ボタン(明るめ)
destructive-foreground白削除ボタン上のテキスト
border800境界線
input800入力欄の境界線
ring500フォーカスリング
ダークモードの反転パターン

ダークモードでは、色相と彩度を保ちながら明度を反転させます。両端の値を入れ替え(50 は 950 に、950 は 50 に)、中間の値は維持します(500 は 500 付近のままです)。

ライトのシェードダークの相当色役割
50950背景
100900控えめな背景
200800ボーダー
500500(やや明るく)ブランドの基準色
600400主要なアクション
95050テキストの色

ダークモードの主な原則:

  • プライマリーにはシェード 600 ではなく 500 を使います。暗い背景でも見やすいよう、より明るい色にします
  • テキストには純白の #FFFFFF ではなく、シェード 50(オフホワイト)を使います。目に優しい色です
  • ボーダーは背景より約 10~15%明るくします(例:背景が 950 の場合、ボーダーは 800)
  • 高いレイヤーほど明るい色にします(ライトモードのシャドウとは逆です)
  • 背景を変更するときは、必ず前景色も更新します

ステップ 4:コントラストを確認する
WCAG の最小コントラスト比
コンテンツの種類AAAAA
通常のテキスト(<18px または <14px の太字)4.5:17:1
大きなテキスト(>=18px または >=14px の太字)3:14.5:1
UI コンポーネント(ボタン、ボーダー)3:1定義なし
グラフィック要素(アイコン、チャート)3:1定義なし

ほとんどのプロジェクトでは AA を目標とし、高いアクセシビリティが必要な場合(政府、医療など)は AAA を目標にします。

輝度とコントラストの計算式
function getLuminance(hex) {
  hex = hex.replace(/^#/, '');
  const r = parseInt(hex.substring(0, 2), 16) / 255;
  const g = parseInt(hex.substring(2, 4), 16) / 255;
  const b = parseInt(hex.substring(4, 6), 16) / 255;
  const rsRGB = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
  const gsRGB = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
  const bsRGB = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
  return 0.2126 * rsRGB + 0.7152 * gsRGB + 0.0722 * bsRGB;
}

function getContrastRatio(hex1, hex2) {
  const lum1 = getLuminance(hex1);
  const lum2 = getLuminance(hex2);
  const lighter = Math.max(lum1, lum2);
  const darker = Math.min(lum1, lum2);
  return (lighter + 0.05) / (darker + 0.05);
}
確認用クイック表 -- ライトモード
前景色背景色比率合格?用途
950white18.5:1AAA本文テキスト
900white14.2:1AAAカードのテキスト
700white8.1:1AAAテキスト
600white5.7:1AAテキスト、ボタン
500white3.9:1不合格テキストには明るすぎます
white6005.7:1AAボタンのテキスト
white7008.1:1AAAボタンのテキスト
600505.4:1AA控えめなセクションのテキスト
確認用クイック表 -- ダークモード
前景色背景色比率合格?用途
5095018.5:1AAA本文テキスト
5090014.2:1AAAカードのテキスト
4009508.2:1AAA控えめなテキスト
4009006.3:1AA控えめなテキスト
white6005.7:1AAボタンのテキスト

経験則:テキストでは、前景色と背景色の明度差を 50%以上にすることを目指します。

確認すべき必須の組み合わせ
  1. 本文テキスト:背景上の前景色(ライト:白地に 950 = 18.5:1、ダーク:950 地に 50 = 18.5:1)
  2. プライマリーボタン:プライマリー上のプライマリー前景色(ライト:600 地に white = 5.7:1、ダーク:500 地に white = 3.9:1 -- 境界線上)
  3. 控えめなテキスト:控えめな色の上の控えめな前景色(ライト:50 地に 600 = 5.4:1、ダーク:800 地に 400 = 4.1:1 -- 不合格の可能性あり)
  4. カードのテキスト:カード上のカード前景色(ライト:白地に 900 = 14.2:1、ダーク:900 地に 50 = 14.2:1)
よくあるコントラスト不足の修正

primary-500 上の白は不合格(3.9:1):代わりに primary-600(5.7:1)を使うか、ボタン上に暗いテキストを使います。

ダークモードの控えめなテキストが不合格(800 上の 400 = 4.1:1):900 上の 300(6.8:1)を使います。

リンクが見づらい(白地に 500 = 3.9:1):primary-700(8.1:1)を使うか、下線を追加します。


ステップ 5:Tailwind v4 CSS を出力する
@import "tailwindcss";

@theme {
  /* Shade scale */
  --color-primary-50: #F0FDFA;
  --color-primary-100: #CCFBF1;
  --color-primary-200: #99F6E4;
  --color-primary-300: #5EEAD4;
  --color-primary-400: #2DD4BF;
  --color-primary-500: #14B8A6;
  --color-primary-600: #0D9488;
  --color-primary-700: #0F766E;
  --color-primary-800: #115E59;
  --color-primary-900: #134E4A;
  --color-primary-950: #042F2E;

  /* Light mode semantic tokens */
  --color-background: #FFFFFF;
  --color-foreground: var(--color-primary-950);
  --color-card: #FFFFFF;
  --color-card-foreground: var(--color-primary-900);
  --color-popover: #FFFFFF;
  --color-popover-foreground: var(--color-primary-950);
  --color-primary: var(--color-primary-600);
  --color-primary-foreground: #FFFFFF;
  --color-secondary: var(--color-primary-100);
  --color-secondary-foreground: var(--color-primary-900);
  --color-muted: var(--color-primary-50);
  --color-muted-foreground: var(--color-primary-600);
  --color-accent: var(--color-primary-100);
  --color-accent-foreground: var(--color-primary-900);
  --color-destructive: #DC2626;
  --color-destructive-foreground: #FFFFFF;
  --color-border: var(--color-primary-200);
  --color-input: var(--color-primary-200);
  --color-ring: var(--color-primary-600);
  --radius: 0.5rem;
}

/* Dark mode overrides */
.dark {
  --color-background: var(--color-primary-950);
  --color-foreground: var(--color-primary-50);
  --color-card: var(--color-primary-900);
  --color-card-foreground: var(--color-primary-50);
  --color-popover: var(--color-primary-900);
  --color-popover-foreground: var(--color-primary-50);
  --color-primary: var(--color-primary-500);
  --color-primary-foreground: #FFFFFF;
  --color-secondary: var(--color-primary-800);
  --color-secondary-foreground: var(--color-primary-50);
  --color-muted: var(--color-primary-800);
  --color-muted-foreground: var(--color-primary-400);
  --color-accent: var(--color-primary-800);
  --color-accent-foreground: var(--color-primary-50);
  --color-destructive: #EF4444;
  --color-destructive-foreground: #FFFFFF;
  --color-border: var(--color-primary-800);
  --color-input: var(--color-primary-800);
  --color-ring: var(--color-primary-500);
}

assets/tailwind-colors.css を開始用テンプレートとしてコピーします。


コンポーネントの使用例

// Primary button
<button className="bg-primary text-primary-foreground hover:bg-primary/90">Click me</button>

// Secondary button
<button className="bg-secondary text-secondary-foreground hover:bg-secondary/80">Cancel</button>

// Card
<div className="bg-card text-card-foreground border-border rounded-lg">
  <h2>Title</h2>
  <p className="text-muted-foreground">Description</p>
</div>

// Input
<input className="bg-background text-foreground border-input focus:ring-ring" />

よくある調整

  • 明るいシェードが鮮やかすぎる:彩度を 10~20%下げます
  • プライマリーのコントラストが低い:テキストにはシェード 700 以上を使います
  • ダークモードが暗すぎる:背景に 950 ではなく 900 を使います
  • ブランドカラーが明るすぎる/暗すぎる:シェード 500~600 の範囲に調整します
  • ダークモードがくすんで見える:プライマリーにシェード 500 を使います(ライトモードの 600 より明るい色です)
  • ダークモードで純白のテキストが強すぎる:代わりにシェード 50(オフホワイト)を使います
  • ダークモードの控えめなテキストがコントラスト不足になる:より差の大きいシェードを使います(400 を 800 に載せる代わりに、300 を 900 に載せます)
ブランドアイデンティティの調整
  • 保守的なブランド(金融、法律):ボタンには primary-700 を使用し、明るい色合いでは彩度を下げます
  • 鮮やかなブランド(クリエイティブ、テクノロジー):primary-500-600 を使用し、彩度を保ちます
  • ミニマルなブランド(デザイン、建築):primary の使用を控えめにし、落ち着いた色調と控えめな境界線(primary-100)を重視します

検証チェックリスト

  • 本文テキスト:4.5:1 以上(通常サイズ)または 3:1 以上(大きいサイズ)
  • プライマリボタンのテキスト:4.5:1 以上
  • セカンダリボタンのテキスト:4.5:1 以上
  • 控えめなテキスト:4.5:1 以上
  • リンク:4.5:1 以上(または下線付き)
  • UI 要素(境界線):3:1 以上
  • フォーカスインジケーター:3:1 以上
  • エラーテキスト:4.5:1 以上
  • ダークモード:上記のチェック項目をすべて満たす
  • すべての背景に対応する前景色がある
  • どちらのモードでもブランドカラーを認識できる
  • 境界線が見やすく、強すぎない
  • カードやセクションの境界が明確

リリース前に両方のモードをテストしてください。


参考資料(任意)

  • オンラインのコントラストチェッカー:WebAIM (webaim.org/resources/contrastchecker)、Coolors (coolors.co/contrast-checker)、Accessible Colors (accessible-colors.com)
  • CI/CD のコントラストテスト:テストスイートで getContrastRatio() を使用し、すべてのトークンの組み合わせが最小比率を満たすことを検証します
  • 透明色/グラデーションの特殊なケース:不透明度のある色は、最終的に描画された色に対して計算します。グラデーションは両端を確認します。
  • OLED のダークモード:AMOLED 画面でバッテリーを節約するため、背景に #000000 を使用する @media (prefers-contrast: high) を使います
  • 複数色のパレット:ブランドカラーごとに個別の濃淡スケールを生成し、異なるセマンティックロール(primary、accent)に割り当てます
  • パレットの可視化ツール:coolors.co、paletton.com、Figma のスウォッチ
  • assets/tailwind-colors.css — CSS 出力テンプレート一式

コメント