mcpField
C
color-palette

color-palette

github.com/arnavpuriデザイン・UI17133 回インストール5 週間前に更新
リポジトリ

color-palette について

起点となる色から、OKLCH のスケールやセマンティックトークンを含む配色システムを作るデザインスキルです。CSS や Tailwind に色を適用するデザイナーや開発者向けです。

主な機能

  1. 0150〜950 の OKLCH スケール生成
  2. 02ブランド・セマンティック・ニュートラルトークンの定義
  3. 03WCAG コントラストの確認
  4. 04ダークモードのトークン割り当て提案
  5. 05Tailwind 設定と CSS 変数の作成
  6. 06色見本の確認と design-context 更新の案内

活用シーン

  1. 01ブランドカラーから色階調を展開
  2. 02テキストと背景のコントラスト確認
  3. 03CSS や Tailwind 用の色トークン作成
  4. 04ダークテーマ向けのセマンティックカラー割り当て

インストール

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

$npx skills add https://github.com/arnavpuri/designskills --skill color-palette

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

同梱ファイルscripts/palette.py

詳細

カラーパレットの生成

任意の開始色から、調和が取れ、アクセシブルで、本番環境に対応したカラーシステムを生成します。

前提条件

色を生成する前に、既存のデザインコンテキストを確認します。

  • .agents/design-context.md(design-context スキルを参照)を読みます。Color System が定義されている場合、その HEX 値を正として扱い、置き換えるのではなく拡張してください。
  • コードベースに既存のデザインシステム(CSS 変数、Tailwind テーマ、tokens.json)がある場合、置き換えるのではなく拡張してください。

命名規則(design-system、layout-composition などと共有): プリミティブスケールは --brand-50 … --brand-950、--gray-50 … --gray-950、--success-*、--warning-*、--error-*、--info-* です。セマンティックトークンは --bg-*、--text-*、--border-*、--interactive-* に加え、ブランドエイリアスの --color-primary、--color-secondary、--color-accent です。


ステップ 1:色彩理論の基本を理解する

パレットは OKLCH で生成します。明度チャンネルは知覚的に均等なため、明度の変化量が一定なら、どの色相でも同じ視覚的な変化になります(HSL では、「同じ」明度でも hsl(60 100% 50%) の黄色は hsl(240 100% 50%) の青よりはるかに明るく見えます)。従来のツールで必要な場合に限り、HSL を使用します。彩度の高い OKLCH 値は sRGB の範囲外になることがあるため、HEX に変換する際は明度と色相を保ったまま彩度を下げてください。

色相環の関係
調和基準色からの角度印象
補色180°高コントラストで、活気がある
類似色±30°調和が取れ、自然
三色配色120°、240°鮮やかで、バランスが取れている
分裂補色150°、210°緊張感を抑えたコントラスト
四色配色90°、180°、270°豊かだが、慎重なバランスが必要
OKLCH で調和色を生成する
:root {
  /* Base brand color in oklch */
  --brand-hue: 250;         /* hue angle */
  --brand-chroma: 0.15;     /* chroma (not HSL saturation) */
  --brand-l: 0.55;          /* lightness */

  --color-primary:       oklch(var(--brand-l) var(--brand-chroma) var(--brand-hue));
  --color-complement:    oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 180));
  --color-analogous-1:   oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 30));
  --color-analogous-2:   oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) - 30));
  --color-triadic-1:     oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 120));
  --color-triadic-2:     oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 240));
  --color-split-comp-1:  oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 150));
  --color-split-comp-2:  oklch(var(--brand-l) var(--brand-chroma) calc(var(--brand-hue) + 210));
}

ステップ 2:色の濃淡スケール全体を生成する(50~950)

1 色のブランドカラーから、明度を 11 段階にしたスケール(50、100~900、950)を生成します。OKLCH では、色相を一定に保ち、両端で彩度を少し下げながら明度を変化させます。

明度マップ
トークンOKLCH 明度用途
500.97色味のある背景
1000.93ホバー時の背景
2000.87アクティブ時の背景
3000.78ボーダー
4000.68プレースホルダーテキスト
5000.55基本色/主要なアクション
6000.48主要なアクションのホバー時
7000.40主要なアクションのアクティブ時
8000.32明るい背景上の見出し
9000.24明るい背景上の本文テキスト
9500.16高コントラストのテキスト
CSS の実装
:root {
  --brand-hue: 250;
  --brand-chroma: 0.15;

  --brand-50:  oklch(0.97 calc(var(--brand-chroma) * 0.3) var(--brand-hue));
  --brand-100: oklch(0.93 calc(var(--brand-chroma) * 0.4) var(--brand-hue));
  --brand-200: oklch(0.87 calc(var(--brand-chroma) * 0.5) var(--brand-hue));
  --brand-300: oklch(0.78 calc(var(--brand-chroma) * 0.7) var(--brand-hue));
  --brand-400: oklch(0.68 calc(var(--brand-chroma) * 0.85) var(--brand-hue));
  --brand-500: oklch(0.55 var(--brand-chroma) var(--brand-hue));
  --brand-600: oklch(0.48 var(--brand-chroma) var(--brand-hue));
  --brand-700: oklch(0.40 var(--brand-chroma) var(--brand-hue));
  --brand-800: oklch(0.32 calc(var(--brand-chroma) * 0.9) var(--brand-hue));
  --brand-900: oklch(0.24 calc(var(--brand-chroma) * 0.8) var(--brand-hue));
  --brand-950: oklch(0.16 calc(var(--brand-chroma) * 0.7) var(--brand-hue));
}

ステップ 3:セマンティックカラーを定義する

用途別のトークンをパレットに割り当てるか、独立した色相を定義します。

推奨するセマンティックカラーの色相
役割色相(OKLCH)理由
成功145緑。普遍的な「進め」の色
警告85琥珀色/黄色。注意喚起
エラー25赤。緊急性
情報230青。中立的な情報
:root {
  /* Semantic: success */
  --success-50:  oklch(0.97 0.04 145);
  --success-400: oklch(0.68 0.15 145);  /* dark-mode foreground */
  --success-500: oklch(0.55 0.16 145);
  --success-700: oklch(0.40 0.14 145);

  /* Semantic: warning */
  --warning-50:  oklch(0.97 0.04 85);
  --warning-400: oklch(0.72 0.15 85);
  --warning-500: oklch(0.60 0.16 85);   /* ~4:1 on white: use dark text ON it, 700 for warning TEXT */
  --warning-700: oklch(0.45 0.14 85);

  /* Semantic: error */
  --error-50:  oklch(0.97 0.04 25);
  --error-400: oklch(0.68 0.16 25);
  --error-500: oklch(0.55 0.18 25);
  --error-700: oklch(0.40 0.16 25);

  /* Semantic: info */
  --info-50:  oklch(0.97 0.04 230);
  --info-400: oklch(0.68 0.12 230);
  --info-500: oklch(0.55 0.14 230);
  --info-700: oklch(0.40 0.12 230);
}

製品で必要な場合(アラート、バッジ、グラフなど)に限り、セマンティックカラーの色相について 50~950 のスケール全体を生成します。ほとんどの UI では 50/400/500/700 で十分です。


ステップ 4:ニュートラルスケールを生成する

ニュートラルカラーは基盤となる要素です。ブランドカラーの色相をわずかに加えて、温かみを持たせます。

:root {
  --neutral-hue: var(--brand-hue);
  --neutral-chroma: 0.01; /* barely tinted */

  --gray-50:  oklch(0.98 var(--neutral-chroma) var(--neutral-hue));
  --gray-100: oklch(0.96 var(--neutral-chroma) var(--neutral-hue));
  --gray-200: oklch(0.90 var(--neutral-chroma) var(--neutral-hue));
  --gray-300: oklch(0.83 var(--neutral-chroma) var(--neutral-hue));
  --gray-400: oklch(0.71 var(--neutral-chroma) var(--neutral-hue));
  --gray-500: oklch(0.55 var(--neutral-chroma) var(--neutral-hue));
  --gray-600: oklch(0.45 var(--neutral-chroma) var(--neutral-hue));
  --gray-700: oklch(0.37 var(--neutral-chroma) var(--neutral-hue));
  --gray-800: oklch(0.27 var(--neutral-chroma) var(--neutral-hue));
  --gray-900: oklch(0.20 var(--neutral-chroma) var(--neutral-hue));
  --gray-950: oklch(0.13 var(--neutral-chroma) var(--neutral-hue));
}

ステップ 5:WCAG アクセシビリティを確保する

コントラスト要件(WCAG 2.2 -- 現行の法的/業界標準)
レベル通常のテキスト大きなテキスト(≥24px、または ≥18.66px/14pt 太字)テキスト以外の UI(アイコン、境界線、フォーカスリング、グラフのマーク)
WCAG AA4.5:13:1隣接色とのコントラストが 3:1(SC 1.4.11)
WCAG AAA7:14.5:1--

コントラスト比 = (L1 + 0.05) / (L2 + 0.05)。L1/L2 は、線形化した sRGB における明るい方/暗い方の相対輝度です(0.2126 R + 0.7152 G + 0.0722 B)。比率は切り上げません。4.49:1 は不適合です。APCA(Lc 値)は WCAG 3 の草案候補です。特にダークモードではセカンドオピニオンとして有用ですが、適合性の基準として報告してはいけません。

実践的なルール
  • 明るい背景上の本文:900 または 950 の色合いを使います(上記の明度マップでは AA に十分適合します)。
  • 暗い背景上の本文:50 または 100 の色合いを使います。
  • プライマリボタン:500 以上の色合いに白いテキストを使うと、通常は適合します(L 0.55 の青は約 4.9:1)。ただし、L 0.55~0.65 の黄色/アンバー/シアンは不適合になることが多いため、暗い色のテキストを使います。必ず測定してください。
  • 無効状態:明るい背景には 400 の色合いを使います。無効な要素は WCAG の適用対象外ですが、それでも見分けられるようにしてください。
  • リンク:色だけに頼らず、周囲のテキストと区別できる必要があります。下線を付けるか、周囲のテキストとのコントラストを 3:1 にし、さらにホバー/フォーカス時に色以外の手掛かりを加えます。
OKLCH の明度を使ったコントラストの簡易チェック

ほぼ無彩色の色では、相対輝度 ≈ L³ となるため、極端な明度の場合に 4.5:1 を得るには約 0.42~0.45 以上の明度差が必要です(中間域ではさらに大きな差が必要です)。候補選びにのみ使い、その後に測定してください。

text L 0.20 | bg L 0.97 | diff 0.77 -> ~16.6:1, passes AAA
text L 0.55 | bg L 0.97 | diff 0.42 -> ~4.5:1, borderline AA -- measure; safe for large text
text L 0.57 | bg L 0.97 | diff 0.40 -> ~4.1:1, FAILS AA for normal text
推測せず、測定する

ブラウザーは OKLCH を直接描画しますが、デザインコンテキストでは HEX を保存し、コントラストは sRGB で計算する必要があります。同梱スクリプトを使います(<color-palette> と <design-context> は各スキルのディレクトリです)。

python <color-palette>/scripts/palette.py --from "#2563eb"                 # scale around a brand color
python <color-palette>/scripts/palette.py 250 0.15 --name brand --css      # hue + chroma -> CSS vars
python <color-palette>/scripts/palette.py 250 0.02 --name gray --json      # neutrals as JSON
python <design-context>/scripts/contrast.py "#ffffff" "#2563eb"             # any real pairing

palette.py は各段階の HEX 値と、白/黒に対するコントラストを出力し、AA(4.5:1)、large/UI(3:1)、または - のマークを付けます。色域外の段階では、明度や色相ではなく彩度が下がります。contrast.py は不適合の場合に終了コード 1 で終了し、最も近い適合色合いを提案します。

実際に提供する、テキストと背景のすべての組み合わせ(--bg-* 上のテキスト、--interactive-* 上のボタンラベル、ダークモードの組み合わせ)も確認してください。純粋な白/黒との比較だけでは不十分です。


ステップ 6:ダークモードへの適応

単純にスケールを反転しないでください。代わりに、セマンティックな用途を再マッピングします。

ダークモードの方針
[data-theme="dark"] {
  /* Backgrounds: use 900/950 instead of 50/white */
  --bg-primary:   var(--gray-950);
  --bg-secondary: var(--gray-900);
  --bg-tertiary:  var(--gray-800);

  /* Text: use 50/100 instead of 900/950 */
  --text-primary:   var(--gray-50);
  --text-secondary: var(--gray-300);
  --text-tertiary:  var(--gray-400);

  /* Surfaces: slightly lighter than bg */
  --surface:       var(--gray-900);
  --surface-hover: var(--gray-800);

  /* Borders: use 700 instead of 200 */
  --border-default: var(--gray-700);

  /* Brand colors: increase lightness for dark bg */
  --interactive-primary: var(--brand-400); /* lighter than 500 */

  /* Semantic: bump to lighter shades */
  --color-success: var(--success-400);
  --color-warning: var(--warning-400);
  --color-error:   var(--error-400);
}

これらの名前は、ステップ 10 のライトモードのレイヤー 2 トークンと一致させる必要があります。ダークモードでは、それらを再マッピングするだけです。完全なダークテーマ(エレベーションサーフェス、画像、トグル)については、dark-mode スキルに引き継いでください。

主な原則
  1. コントラストを少し下げます。純白と純黒の組み合わせは刺激が強いため、gray-950 上では gray-50 を使います。
  2. ダークモードでは彩度を少し下げます。彩度の高い色は暗い背景で発光しているように見えます。
  3. ダークモードのエレベーションには、より明るいサーフェスを使います(ライトモードのシャドウとは逆です)。

ステップ 7:業界別の色彩心理

業界主な色理由
金融ネイビー、ダークブルー、緑信頼、安定、成長
医療・健康青、ティール、白落ち着き、清潔感、信頼
食品赤、オレンジ、黄色食欲、活力、温かみ
テクノロジー/SaaS青、バイオレット、シアン革新、信頼性
高級品黒、金、濃い紫優雅さ、特別感
環境・エコ緑、アースカラー自然、持続可能性
教育青、オレンジ、緑信頼、熱意、成長
クリエイティブ鮮やかなプライマリカラー、ネオンカラー活力、自己表現、楽しさ

ステップ 8:グラデーションの組み合わせ

効果的なグラデーションのルール
  1. 控えめなグラデーションにするには、色相の回転を 60 度以内に保ちます。
  2. 鮮やかでエネルギッシュなグラデーションには、90〜180 度を使用します。
  3. 停止色を oklch() で記述しても、グラデーションが OKLCH で補間されるわけではありません。補間ヒントを指定しない場合、ブラウザーはモダンな色には Oklab を、hex/rgb/hsl の停止色には sRGB を使用します。どちらも色空間を直線的に進むため、色相が離れていると、その間にあるグレーを通ることがあります。色相環に沿って補間するには in oklch を追加します(虹色のように色相を一周させるには longer hue を追加します)。
  4. または、中間色に彩度を少し加えて、「グレーのデッドゾーン」を避けます。
/* Subtle brand gradient */
.gradient-subtle {
  background: linear-gradient(
    135deg in oklch,
    oklch(0.55 0.15 250),
    oklch(0.55 0.15 280)
  );
}

/* Vibrant hero gradient */
.gradient-vibrant {
  background: linear-gradient(
    135deg in oklch,
    oklch(0.65 0.20 280),
    oklch(0.60 0.22 330),
    oklch(0.65 0.20 20)
  );
}

/* Mesh gradient (modern trend) */
.gradient-mesh {
  background:
    radial-gradient(at 0% 0%, oklch(0.70 0.15 280) 0%, transparent 50%),
    radial-gradient(at 100% 0%, oklch(0.70 0.15 200) 0%, transparent 50%),
    radial-gradient(at 100% 100%, oklch(0.70 0.15 330) 0%, transparent 50%),
    oklch(0.97 0.01 250);
}

ステップ 9:Tailwind 設定の生成

Tailwind v4(CSS ファースト)――スケールを @theme に記述すると、bg-brand-500、text-brand-900 などが生成されます。

@import "tailwindcss";
@theme {
  --color-brand-50:  oklch(0.97 0.045 250);
  --color-brand-500: oklch(0.55 0.15 250);
  --color-brand-900: oklch(0.24 0.12 250);
  /* ...every step 50-950, plus success/warning/error/info */
}

Tailwind v3(tailwind.config.js):

// tailwind.config.js
const brand = {
  50:  'oklch(0.97 0.045 250)',
  100: 'oklch(0.93 0.06 250)',
  200: 'oklch(0.87 0.075 250)',
  300: 'oklch(0.78 0.105 250)',
  400: 'oklch(0.68 0.1275 250)',
  500: 'oklch(0.55 0.15 250)',
  600: 'oklch(0.48 0.15 250)',
  700: 'oklch(0.40 0.15 250)',
  800: 'oklch(0.32 0.135 250)',
  900: 'oklch(0.24 0.12 250)',
  950: 'oklch(0.16 0.105 250)',
};

module.exports = {
  theme: {
    extend: {
      colors: {
        brand,
        success: { /* ... same pattern, hue 145 */ },
        warning: { /* ... same pattern, hue 85 */ },
        error:   { /* ... same pattern, hue 25 */ },
        info:    { /* ... same pattern, hue 230 */ },
      },
    },
  },
};

ステップ 10:CSS カスタムプロパティのアーキテクチャ

トークンを 3 層に分けて構成します。

/* Layer 1: Primitive (raw values) */
:root {
  --brand-500: oklch(0.55 0.15 250);
  --error-500: oklch(0.55 0.18 25);
  /* ...full --brand-*, --gray-*, semantic scales from Steps 2-4 */
}

/* Layer 2: Semantic (purpose) -- same names design-system uses */
:root {
  --color-primary:       var(--brand-500);
  --interactive-primary: var(--brand-500);
  --color-error:         var(--error-500);
  --bg-primary:          var(--gray-50);
  --text-primary:        var(--gray-900);
  --border-default:      var(--gray-200);
}

/* Layer 3: Component (scoped) */
.btn-primary {
  background: var(--interactive-primary);
  color: white; /* verified >= 4.5:1 against brand-500 */
}

この 3 層構成により、テーマ設定とダークモードの実装が簡単になります。レイヤー 2 を再マッピングするだけです。


ステップ 11:視覚的に確認してデザインコンテキストに保存する

  1. スウォッチシートをレンダリングする:小さな HTML ファイル(スクラッチパッド)を作成し、各スケールをスウォッチの行として表示します。トークン、hex 値、白/黒とのコントラストをラベルに記載し、ライトモードとダークモードの両方でテキストとボタンの組み合わせも表示します。スクリーンショットを撮影し(例:npx playwright screenshot --full-page "file://$PWD/swatches.html" swatches.png。ダークモードで撮影する場合は --color-scheme=dark を追加します)、Read で画像を確認します。各段階が均等に見えること、濁った色やネオンのような色がないこと、ニュートラルカラーがニュートラルに見えることを確認します。
  2. .agents/design-context.md(design-context スキルのファイル)への書き戻しを提案する。変更された Color System の行だけを更新し、ファイル全体を書き換えないでください。スケールの値をデザインコンテキストの役割に、hex 値として対応付けます。
デザインコンテキストの役割使用する値
プライマリ--brand-500(または白いテキストとのコントラスト比が 4.5:1 を満たさない場合は 600)
プライマリライト/プライマリダーク--brand-400 / --brand-700
セカンダリ/アクセントセカンダリ/アクセントの色相の 500 段階
ニュートラル 50/100/200/500/800/900対応する --gray-* の段階
成功/警告/エラー--success-500 / --warning-500 / --error-500

変更した行の変更前/変更後の差分をユーザーに提示し、保存する前に確認を求めます。


クイックリファレンス:1 つの hex 値からパレットを作成する

  1. .agents/design-context.md を読み込み、ブランドの hex 値を OKLCH に変換します。
  2. 色相を抽出します。これがブランドの色相です。
  3. ステップ 2 の明度マップを使用して、50〜950 のスケールを生成します。
  4. ブランドの色相で色味を付けたニュートラルカラーを生成します(ステップ 4)。
  5. セマンティックカラーの色相を選びます(ステップ 3)。
  6. palette.py/contrast.py でコントラストを測定します(ステップ 5)。続行する前に、基準を満たさない箇所を修正します。
  7. ダークモード用の再マッピングを作成します(ステップ 6)。
  8. CSS カスタムプロパティまたは Tailwind 設定としてエクスポートします。
  9. スウォッチシートをレンダリングして確認し、hex 値をデザインコンテキストに保存することを提案します(ステップ 11)。

コメント