小さなデザインシステムを作る
レッスン7:小さなデザインシステムを作る
このレッスンで学ぶこと
- デザイントークンという考え方と、色・余白・文字・角丸・影の決め方を理解する
- 部品カタログという発想と、デザイナーとの共通言語という視点を身につける
- 守られないルールはルールが厳しすぎるからだという原則を理解する
- ルールの更新運用をどう設計するかを理解する
前回のレッスンでは、役割にもとづく設計とユーティリティファーストという、対照的な 2 つの考え方を比較しました。今回は、これまでのレッスンで学んできた命名・変数・部品化・設計方針の選び方を統合し、小さな「デザインシステム」として組み立てる方法を学びます。
デザインシステムとは何か
デザインシステムという言葉は幅広い意味で使われますが、本レッスンでは次のように定義します。色・余白・文字といった基本の値と、ボタンやカードといった部品の集まりを、チームで共有できる形にまとめたものです。
大がかりな仕組みを新たに導入する必要はありません。レッスン3 で学んだカスタムプロパティと、レッスン5 で学んだ部品の設計を、意識的に一箇所に集めて整理するだけでも、小さなデザインシステムの土台になります。
flowchart TD
A[デザイントークン<br/>色・余白・文字・角丸・影] --> B[部品<br/>ボタン・カード・フォーム]
B --> C[ページ<br/>部品を組み合わせた画面]
この図は、デザインシステムの階層を表しています。もっとも基礎になるのがデザイントークンで、その上に部品が組み立てられ、さらにその部品を組み合わせてページが作られるという積み上げの構造です。上の層は下の層に依存しますが、下の層は上の層を知らないという関係は、レッスン5 で扱った「部品は置かれる場所を知らない」という原則と同じ発想です。
デザイントークン——値に名前を付けて管理する
デザイントークンとは、色・余白・文字サイズ・角丸・影といった、デザイン上の基本的な値に名前を付けたものです。レッスン3 で学んだ CSS カスタムプロパティは、デザイントークンを CSS の中で実現するための代表的な手段です。
:root {
/* 色 */
--color-brand: #2c6cd4;
--color-text: #2c2c2c;
--color-danger: #e74c3c;
/* 余白 */
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 32px;
/* 文字 */
--font-size-sm: 14px;
--font-size-md: 16px;
--font-size-lg: 24px;
/* 角丸 */
--radius-sm: 4px;
--radius-lg: 12px;
/* 影 */
--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.1);
}
デザイントークンをまとめる際の目安は、「どのくらいの種類を用意するか」を先に決めておくことです。余白を 3 段階(sm・md・lg)に絞るのか、5 段階に広げるのかによって、あとから部品を作るときの迷いやすさが変わります。種類が少なすぎると微調整のたびに新しい値を追加したくなり、多すぎるとどれを選べばよいか判断に迷います。
.card {
padding: var(--spacing-md);
border-radius: var(--radius-sm);
box-shadow: var(--shadow-card);
}
.button {
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-sm);
background: var(--color-brand);
}
部品側は、デザイントークンの名前だけを組み合わせて見た目を組み立てています。個別の数値を部品ごとに書き直す必要がなく、トークンの値を変えれば、それを使っているすべての部品に一括で反映されます。
💡 ポイント デザイントークンの名前は、レッスン2 で学んだ「役割で名付ける」考え方をそのまま踏襲します。
--color-brandは「ブランドカラーという役割」を、--spacing-mdは「中くらいの余白という役割」を語る名前です。値そのものではなく、値の意味を名前にするという考え方は、CSS のクラス名でもデザイントークンでも共通しています。
トークンを 2 段階に分ける
デザイントークンの運用に慣れてくると、もう 1 段階工夫を加えられます。生の値そのものを表すトークンと、用途にもとづいたトークンを分けて 2 段階にする方法です。
:root {
/* 生の値そのもの(どんな色があるかの一覧) */
--blue-600: #2c6cd4;
--blue-800: #1a4fa0;
--gray-200: #e5e5e5;
--red-600: #e74c3c;
/* 用途にもとづくトークン(生の値を参照する) */
--color-brand: var(--blue-600);
--color-brand-hover: var(--blue-800);
--color-border: var(--gray-200);
--color-danger: var(--red-600);
}
.button--primary {
background: var(--color-brand);
}
.button--primary:hover {
background: var(--color-brand-hover);
}
部品側は、常に「用途にもとづくトークン」(--color-brand など)だけを参照し、「生の値そのもの」(--blue-600 など)を直接使いません。この 2 段階の構造には利点があります。ブランドカラーを別の青系の色に差し替えたいとき、--color-brand が参照する先を書き換えるだけで済み、色の一覧そのもの(--blue-600 など)は変更せずに残しておけます。逆に、新しい色をパレットに追加したいときは、まず生の値として追加し、それから用途にもとづくトークンとして意味づけるという順番で進められます。
📖 もっと詳しく この 2 段階の考え方は、小規模なプロジェクトでは必須ではありません。色や余白の種類が少ないうちは、レッスン3 で学んだ単純な 1 段階のカスタムプロパティで十分です。部品の数やテーマの種類が増えてきて、色の一覧と用途の対応関係を整理したくなったタイミングで導入を検討する、応用的な選択肢の 1 つとして捉えてください。
部品カタログという発想
デザイントークンの上に積み上がるのが部品です。部品が増えてくると、「いまどんな部品が存在するか」を一覧できる場所が必要になります。これが部品カタログという発想です。
部品カタログは、特別な専用ツールを導入しなくても、簡易的には 1 枚の HTML ページとしても作れます。
<section class="catalog-section">
<h2>ボタン</h2>
<button class="button button--primary">プライマリ</button>
<button class="button button--secondary">セカンダリ</button>
<button class="button button--primary" disabled>無効</button>
</section>
<section class="catalog-section">
<h2>カード</h2>
<div class="card">
<h3 class="card__title">見出し</h3>
<p class="card__body">本文のサンプルです。</p>
</div>
</section>
このページには実際の業務データは何も含まれておらず、部品そのものの見た目だけを一覧できるようになっています。新しく参加したメンバーは、このページを見るだけで「すでにどんな部品が存在するか」を把握でき、似たような部品をゼロから作り直してしまう事故を防げます。
📝 補足 部品カタログを自動生成する専用のツールも存在しますが、本レッスンでは考え方の紹介にとどめます。小さなプロジェクトであれば、簡易的な一覧ページを手作業で用意するだけでも十分に効果があります。
デザイナーとの共通言語
部品カタログのもう 1 つの効果は、デザイナーとエンジニアが同じ言葉で会話できるようになることです。デザイナーが新しい要望を伝えるとき、部品カタログという共通の参照先があると、会話がスムーズに進みます。
例えば、デザイナーが「カードの注目バリエーションを追加したい」と伝えたとします。エンジニアは部品カタログを確認し、.card--featured という既存のバリエーションで対応できるかどうかをその場で答えられます。部品カタログという共通の参照先がなければ、「どのカードのことか」「見た目をどう変えたいのか」を一から言葉で説明し合う必要があり、認識のずれも生まれやすくなります。
デザイナーが「あのボタンをもう少し目立たせたい」と言ったとき、部品カタログに .button--primary という名前が存在していれば、「どのボタンか」「どのバリエーションを指しているか」がすぐに一致します。
名前という土台が共有されていないと、「あの青いボタン」「トップページの右上のボタン」のように、見た目や場所での言い方に頼ることになり、認識のずれが生まれやすくなります。デザイントークンと部品の名前は、デザイナーとエンジニアの間の共通言語としても機能します。
ルールは少ないほど守られる
デザインシステムを作ろうとすると、細かいルールをたくさん決めたくなります。ですが、ルールの数と、実際に守られる度合いは、多くの場合反比例します。
中核メッセージ 6:守られないルールは、ルールが厳しすぎるからです。
/* ルールが細かすぎる例 */
:root {
--spacing-1: 2px;
--spacing-2: 4px;
--spacing-3: 6px;
--spacing-4: 8px;
--spacing-5: 10px;
--spacing-6: 12px;
--spacing-7: 14px;
--spacing-8: 16px;
/* ...さらに続く */
}
余白を 2px 刻みで何十段階にも分けると、理論上はどんな余白の値にも対応できます。ですが、実際に部品を作る人は、どの段階を選べばよいか毎回迷うことになります。選択肢が多すぎるルールは、結局のところ「好きな値を直接書いてしまう」という抜け道を生み、ルール自体が形骸化していきます。
/* 十分に運用できる例 */
:root {
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 32px;
}
段階を 3〜5 種類程度に絞ると、選ぶときに迷う余地が減り、結果としてルールが実際に守られやすくなります。ルールを作る目的は「あらゆる状況を網羅すること」ではなく「多くの場合に迷わず選べること」です。
⚠️ 注意 ルールを厳しくすればするほど品質が上がるという発想は、直感に反するかもしれませんが、実際の運用ではしばしば逆の結果を招きます。細かすぎるルールは、守る側の負担を増やし、結果的に無視されるルールを生み出します。
更新の運用
デザインシステムは、一度作って終わりではありません。事業やデザインの方針が変われば、トークンや部品も更新が必要になります。運用を続けるうえでの基本的な考え方を 2 つ紹介します。
1 つ目は、トークンの値を直接書き換えるだけで、多くの見た目を一括更新できる状態を保つことです。レッスン3 で学んだカスタムプロパティの利点がここで生きます。ブランドカラーを変更したいとき、--color-brand の値を 1 か所書き換えるだけで済むなら、更新のコストは小さく保てます。
:root {
--color-brand: #1a5fb4; /* この1行を書き換えるだけで全体に反映される */
}
2 つ目は、部品カタログを、実際の部品の実装から自動的に、あるいは定期的に見直す機会を設けることです。カタログと実装がずれてしまうと、カタログを見ても実際の見た目と違うという事態が起こり、カタログ自体が信頼されなくなります。新しい部品を追加したり、既存の部品のバリエーションを変えたりするたびに、カタログ側も一緒に更新する習慣が欠かせません。
🔰 初学者の方へ 最初から完璧な運用ルールを作ろうとしなくてかまいません。まずは「トークンを 1 箇所にまとめる」「部品を一覧できるページを作る」という 2 つから始め、チームの人数や規模に応じて少しずつ運用のルールを足していくやり方でも十分です。
トークンや部品を変更したときは、変更した理由と影響範囲を短くメモに残しておくと、あとから振り返るときの手がかりになります。特別なツールは必要なく、変更した日付・変更した内容・影響を受ける部品の一覧を、簡単なテキストファイルにまとめておくだけでも効果があります。デザインシステムは一度作って終わりではなく、使いながら少しずつ育てていくものだという前提を持っておくと、更新のたびに身構える必要がなくなります。
講師の現場メモ②——細かすぎるルールを半年で作り直した話
デザインシステムを立ち上げたとき、私は最初からうまくいったわけではありません。最初のバージョンは、余白を 8 段階、色を 20 色以上、文字サイズを 10 段階に分けた、非常に細かいルールとして設計しました。あらゆるデザインの要望に対応できるようにという意図でした。
結果は、意図とは正反対のものでした。デザイナーからもエンジニアからも、「どの余白を選べばいいかわからない」という声が相次ぎました。8 段階の余白のうち、実際に使われていたのは 3 段階だけで、残りはほとんど参照されていませんでした。それどころか、選ぶのが面倒になった一部のメンバーが、トークンを使わずに直接数値を書いてしまう場面まで出てきました。ルールを細かく作りすぎたことが、かえってルールを無視される原因になっていたのです。
半年後、私はこのルールを大幅に作り直しました。余白は 3 段階、色は用途ごとに 6 色程度に絞り込み、「迷ったらこの中から選ぶ」という状態を意識的に作りました。作り直した直後は、デザイナーから「選択肢が減って窮屈にならないか」と心配されましたが、実際に運用してみると、迷う時間が減り、トークンを使わずに直接数値を書く場面も大きく減りました。
この経験から私が得た教訓は、デザインシステムの価値は「網羅性」ではなく「選びやすさ」にあるということです。あらゆる場面に対応できるルールよりも、多くの場面で迷わず選べる少ないルールのほうが、結果として長く運用され続けます。守られないルールを見つけたら、まず疑うべきはルールを守らない人ではなく、ルールの細かさそのものです。
実習:3 段階のデザイントークンを設計する
架空の社内ツールのために、次の条件で小さなデザイントークンを設計してみましょう。
- 色は「ブランドカラー・本文の文字色・エラー色」の 3 種類に絞る
- 余白は「小・中・大」の 3 段階に絞る
- 角丸は「小さい角丸」と「使わない(角丸なし)」の 2 種類に絞る
:root {
/* ここにトークンを定義する */
}
手順は次のとおりです。
- 色・余白・角丸それぞれについて、実際に使う値を決める
- 役割にもとづいた名前(
--color-brandのような形式)を付ける - 決めたトークンを使って、簡単なボタンとカードの部品を組んでみる
- 種類を絞ったことで、選ぶときに迷いが減ったかどうかを振り返る
まとめ
このレッスンでは、以下のことを学びました。
- デザインシステムは、デザイントークン・部品・ページという積み上げの構造を持つこと
- デザイントークンは、色・余白・文字・角丸・影といった値に役割の名前を付けたものであること
- 部品カタログは、既存の部品を一覧でき、デザイナーとエンジニアの共通言語として機能すること
- 守られないルールはルールが厳しすぎることが原因であり、種類を絞るほど実際に運用されやすくなること
- トークンを 1 箇所にまとめ、部品カタログを実装とずれないように保つことが、更新の運用を支えること
次の最終レッスンでは、ここまで学んだ考え方を踏まえて、既存の CSS をどう整理し、チームで保守していくかを扱います。
確認クイズ
このレッスンの理解度をチェックしましょう。