CSSカスタムプロパティでデザイン変数を一元管理する|現場で使える実践テクニック

C
クリオ
Web制作ディレクター / フロントエンジニア

こんにちは!

今日は「CSSカスタムプロパティでデザイン変数を一元管理する」についてお話しします。

僕が色管理で失敗した話

正直に告白するんですけど、僕も過去に色の管理めっちゃ失敗したんです。
昔のプロジェクトで、ボタンの色を#3b79b7って直書きしちゃってて、全部で30箇所ぐらいに散らばってたんですよ。
そしたらクライアントから「色をもうちょっと濃くしてほしい」って言われて…もう大変でした。

30箇所全部を検索と置換で修正する羽目になって、その過程でうっかり背景色まで変わってしまったり、本当にカオスでしたね。
その時に「あ、これ変数化しときゃよかったな」って痛感したんです。

それからはCSSカスタムプロパティを積極的に使うようになって、今は現場でも後輩たちに推奨してるんですよ。
実際に使い始めるとほんま効率が全然違います。

CSSカスタムプロパティの基本的な使い方

では、CSSカスタムプロパティの基本から説明しますね。
カスタムプロパティは、CSS内で変数として機能するもので、--で始まる名前を付けます。

最もシンプルな例を見てみましょう。

:root {
  --primary-color: #3b79b7;
  --secondary-color: #5a9fd4;
  --spacing-unit: 8px;
}

button {
  background-color: var(--primary-color);
  padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
}

.alert {
  color: var(--primary-color);
  border: 1px solid var(--secondary-color);
}

:rootセレクタで定義した変数は、ページ全体で使えます。
var()関数で呼び出すだけです。

これだけでもすごく便利なんですけど、さらに便利なのが「スコープ付きで上書き」できることです。

:root {
  --primary-color: #3b79b7;
}

.dark-mode {
  --primary-color: #ffffff;
}

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

こうすると、.dark-modeクラスが付いた要素の中では、ボタンの背景色が白になるんです。
ダークモード対応とか、複数のテーマを持つサイトでめっちゃ活躍しますよ。

実際の現場で活躍するデザイン変数の設計

ここからは、実際に現場で見かけるデザイン変数の設計パターンをお話しします。
初心者の方も、これを参考にするといい構成ができると思います。

カラーシステムの構築

色の管理が最も重要です。
プライマリ、セカンダリといった基本色だけでなく、状態別の色も一緒に管理するといいですよ。

:root {
  /* ブランドカラー */
  --color-primary: #3b79b7;
  --color-secondary: #5a9fd4;
  --color-accent: #ff6b35;

  /* 状態別の色 */
  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #0ea5e9;

  /* ニュートラルカラー */
  --color-bg-primary: #ffffff;
  --color-bg-secondary: #f9fafb;
  --color-text-primary: #1f2937;
  --color-text-secondary: #6b7280;
  --color-border: #e5e7eb;
}

これだけあれば、ほぼすべての色設定に対応できます。

スペーシングスケールの構築

余白の管理も重要です。
8pxを基準にした倍数で設定すると、デザインに統一感が出ます。

:root {
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-2xl: 48px;
}

.card {
  padding: var(--spacing-lg);
  margin-bottom: var(--spacing-md);
}

.card-title {
  margin-bottom: var(--spacing-sm);
}

タイポグラフィ変数の活用

フォントサイズや行高さも変数化すると、レスポンシブ対応がめっちゃやりやすくなります。

:root {
  --font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-size-xs: 12px;
  --font-size-sm: 14px;
  --font-size-base: 16px;
  --font-size-lg: 18px;
  --font-size-xl: 24px;
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.75;
}

h1 {
  font-size: var(--font-size-xl);
  line-height: var(--line-height-tight);
}

p {
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
}

レスポンシブ対応での上書き

ここが現場あるあるなんですけど、モバイルでは違う余白にしたいとか、ありますよね。
そういう時も変数の上書きが便利です。

:root {
  --spacing-lg: 24px;
  --font-size-xl: 24px;
}

@media (max-width: 768px) {
  :root {
    --spacing-lg: 16px;
    --font-size-xl: 20px;
  }
}

.card {
  padding: var(--spacing-lg);
  /* モバイルではpaddingが自動的に16pxに変わる */
}

これほんま便利なんです。
メディアクエリの中で一箇所だけ変数を上書きすれば、その変数を使ってるすべての要素に反映されます。

フォールバック値の設定

まれに変数が定義されてないケースがあるので、フォールバック値を設定しておくといいですよ。

button {
background-color: var(--primary-color, #3b