>_devtools-hub
CSSデザインシステムフロントエンド

CSSカスタムプロパティでデザインシステムを構築する実践ガイド

CSS Variables(カスタムプロパティ)を使ってカラー・タイポグラフィ・スペーシングを一元管理し、保守性の高いデザインシステムを構築する方法を解説します。

デザインシステムと聞くとFigmaのコンポーネントライブラリや複雑なStorybook構成を思い浮かべるかもしれませんが、CSSカスタムプロパティ(変数)を使えばコードだけでも一貫性のあるデザイントークン体系を構築できます。この記事では、実際のプロダクト開発で使えるカスタムプロパティの設計パターンとダークモード対応の実装方法を紹介します。

なぜカスタムプロパティがデザインシステムに向いているのか

CSS変数(`--variable-name: value`)は通常のCSSプロパティと違い、JavaScriptから動的に変更でき、かつカスケードとスコープを持ちます。Sass変数がビルド時に展開される静的な値であるのに対し、カスタムプロパティはランタイムに評価されるため、ダークモードの切り替えやユーザー設定の反映を再コンパイルなしに実現できます。また、コンポーネントの `style` 属性からカスタムプロパティを渡せるため、ReactやVueなどのフレームワークと組み合わせて動的なスタイリングを実装しやすい点も大きな利点です。

トークンの3層構造:グローバル・セマンティック・コンポーネント

設計上のベストプラクティスとして、デザイントークンを3層に分けることが推奨されています。第1層(グローバルトークン)は具体的な値の定義です。`--color-blue-500: #3b82f6` のように、意味を持たない「生の値」を定義します。この層は1色から機械的に作れます。Color Shade Generator の Scale タブで #3b82f6 を入れ、名前を blue にすると、入力した色を 500 に置いて、明るい 50 から暗い 900 までの10段階が `--color-blue-50` 〜 `--color-blue-900` として出力されます。第2層(セマンティックトークン)は用途別の別名です。`--color-primary: var(--color-blue-500)` のように、グローバルトークンを意味に結びつけます。第3層(コンポーネントトークン)は特定コンポーネント向けのオーバーライドです。`--button-bg: var(--color-primary)` のように、コンポーネント固有の変数がセマンティックトークンを参照します。この3層構造により、テーマ変更時にセマンティックトークンの値を差し替えるだけで、関連する全コンポーネントが一括更新されます。

この手順で使うツール

Color Shade Generator

ベースカラーから Tints / Shades / Tones を自動生成・CSS変数/Tailwind出力

ダークモードの実装パターン

ダークモードは、`:root` にライトの値を定義し、ダーク用の値で上書きします。OSの設定に合わせる `@media (prefers-color-scheme: dark)` と、JavaScriptで手動で切り替える `[data-theme="dark"]` の両方を用意することが多いのですが、ここに落とし穴があります。`@media` の中を `:root` のまま書くと、OSがダークの人が手動でライトを選んでも、メディアクエリの上書きが効いたままでダークから抜けられません。`@media` の中は `:root:not([data-theme="light"])` と書き、手動でライトを選んだときは上書きしないようにします。手動のダークは `:root[data-theme="dark"]` に書きます。もう1つの落とし穴は、同じダークの値を2か所に書くことで、片方に変数を足してもう片方を忘れる、というずれが起きやすい点です。CSS Variable Inspector にCSSを貼り付けて抽出すると、テーマの点検として、ダークを上書きしている場所どうしで変数の漏れがないか、`@media` に手動切替の除外が付いているか、コンポーネントが `background: #ffffff` のように色を直接書いていないか、定義されていない変数を参照していないかを一覧で出します。色を直接書いた宣言はテーマを切り替えても変わらないので、`var(--color-surface)` のようにセマンティックトークン経由に置き換えます。

この手順で使うツール

CSS Variable Inspector

CSSカスタムプロパティを抽出・カラーピッカー/スライダーでリアルタイム編集

スペーシングとタイポグラフィのトークン設計

カラーと同様に、スペーシングとタイポグラフィもトークン化することで一貫性を保てます。スペーシングは `--space-1: 4px`、`--space-2: 8px`、`--space-4: 16px` のように4の倍数で刻むことが多いです。タイポグラフィは、基準の大きさに一定の比率を掛けていくモジュラースケールで決めると、見出しと本文の差に規則が生まれます。Typography Scale Generator で基準を16px、比率を Major Second(1.125)、接頭辞を `--text-` にすると、`--text-sm: 0.89rem`、`--text-base: 1rem`、`--text-md: 1.13rem` のように、比率どおりに計算された値が `:root` の変数として出力されます。比率を大きくするほど見出しが強調されます。フォントファミリーやフォントウェイトも変数化しておくと、ブランドフォントの変更時に1箇所だけ修正すれば済みます。

この手順で使うツール

Typography Scale Generator

Modular Scale からタイポグラフィ階層を自動計算・CSS変数で出力

既存のサイトをトークンに移すとき

すでに動いているサイトにトークンを導入する場合は、まず使われている色を集めて名前を付けるところから始めます。CSS Variable Inspector のテーマの点検で「色を直接書いている宣言」を出すと、どの色がどこに直書きされているかの一覧が手に入ります。そこからブランドの色を選んで名前を付け、Color Token Generator に名前とHEX値を入れると、CSSの変数のほか、Tailwind の設定・Sass の変数・Style Dictionary のJSONの形式でも出力できます。デザイナーとトークンを共有する場合や、CSS以外の環境でも同じ色を使う場合に、同じ定義から各形式を作れるのが利点です。置き換えが進んだら、もう一度点検を流して、直書きの一覧が意図した固定色だけになったことを確かめます。

この手順で使うツール

Color Token Generator

カラーパレットを CSS変数 / Tailwind / Sass / Style Dictionary で一括出力

まとめ

CSSカスタムプロパティによるデザインシステムの核心は「値を一箇所で定義し、セマンティックな名前で参照する」という原則にあります。3層トークン構造を採用し、コンポーネントが生の値ではなく意味のある変数を参照するよう設計することで、テーマ変更・ダークモード対応・ブランドアップデートを最小限のコスト変更で実現できます。特に「@media のダークに :not([data-theme="light"]) を付けないと手動のライトが効かない」「ダークの値を2か所に書くと片方の更新を忘れる」の2点は、書いた本人が気づきにくいので、点検で機械的に確かめるのが確実です。

このツールで試す

CSS Variable Inspector

CSSカスタムプロパティを抽出・カラーピッカー/スライダーでリアルタイム編集

CSS開発者向け

使ってみる →

BOOTH

Color Shade Generator

ベースカラーから Tints / Shades / Tones を自動生成・CSS変数/Tailwind出力

カラーデザインCSS

使ってみる →

BOOTH

Typography Scale Generator

Modular Scale からタイポグラフィ階層を自動計算・CSS変数で出力

CSSデザインタイポグラフィ

使ってみる →

BOOTH

Color Token Generator

カラーパレットを CSS変数 / Tailwind / Sass / Style Dictionary で一括出力

カラーデザイン開発者向け

使ってみる →

BOOTH

関連ガイド