← すべての記事

スタートアップのためのデザインシステム:逆順で構築した理由

私はデザインシステムを逆順で構築しました。多くのアドバイスでは「プロダクトマーケットフィットを待つべき」と言われています。しかし私は、個人サイトでのCLSバグがトークンを省略するコストを教えてくれたため、初日からCSSカスタムプロパティを導入しました。一貫性のないスペーシング値に起因するCumulative Layout Shiftは0.493に達し、原因を突き止めるまでに2回のデバッグセッションを要しました。修正には15分しかかかりませんでしたが、調査には3時間かかりました。トークンがあれば、このバグは完全に防げていたはずです。1

TL;DR

デザインシステムは調整の問題を解決します。1つのプロジェクトを持つソロ開発者には、人と人の間の調整問題はありませんが、過去の自分と未来の自分の間には調整問題があります。blakecrosley.comのデザイントークンシステム——10のカラートークン、13段階のタイプスケール、8つのスペーシング値——を構築した経験から学んだ正しい順序は、トークンは即座に(初日から)、パターンは3回繰り返されたときに、正式なシステムは決して構築しない(ソロプロジェクトの場合)というものです。トークンへの投資は、スペーシングの不整合がレイアウトバグを引き起こす最初のタイミングで元が取れます。


私のデザインシステム:トークンのみ、それ以外は何もなし

カラーの非パレット

サイト全体がブランドカラーを持たない10個のCSSカスタムプロパティで運用されています:

:root {
  --color-bg-dark:        #000000;
  --color-bg-elevated:    #111111;
  --color-bg-surface:     #1a1a1a;
  --color-text-primary:   #ffffff;
  --color-text-secondary: rgba(255,255,255,0.65);
  --color-text-tertiary:  rgba(255,255,255,0.4);
  --color-border:         rgba(255,255,255,0.1);
  --color-border-subtle:  rgba(255,255,255,0.05);
  --color-accent:         #ffffff;
}

4つの透明度ティア(100%、65%、40%、10%)が視覚的な階層構造全体を担っています。すべてのテキストティアは#000000背景に対してWCAG AAAコントラストを満たしています。グラデーションなし、セマンティックカラーなし、ダーク/ライトモードの切り替えもありません。この制約が、コンポーネントライブラリでは改善できないほど一貫性のあるシステムを生み出しています。2

ブランドカラーを省略する決定は、技術的な選択ではなくデザイン上の選択でした。16のプロダクトデザインスタディを通じて、私が最も尊敬するプロダクト(Linear、Vercel、Raycast)が、タイポグラフィで階層構造を表現する抑制されたパレットを使用していることに気づきました。

8ポイントスペーシングシステム

すべてのスペーシング値は8ポイントの基準値から導出されています:

:root {
  --spacing-xs:  0.5rem;  /* 8px */
  --spacing-sm:  1rem;    /* 16px */
  --spacing-md:  1.5rem;  /* 24px */
  --spacing-lg:  2rem;    /* 32px */
  --spacing-xl:  3rem;    /* 48px */
  --spacing-2xl: 4rem;    /* 64px */
  --spacing-3xl: 6rem;    /* 96px */
  --spacing-4xl: 8rem;    /* 128px */
}

任意の値はありません。このシステムには8つのステップが含まれています。レイアウトにシステムに存在しないスペーシングが必要な場合、間違っているのはデザインであり、システムではありません。

--spacing-2xsバグ

このルールは痛い経験から学びました。サブタイトルのmargin-topに--spacing-2xsを使用しましたが、このトークンは:root定義に存在していませんでした。CSSカスタムプロパティはサイレントに失敗します——ブラウザはエラーを投げる代わりに、マージンを適用しませんでした。サブタイトルがヘッドラインに密着し、読み込み時にレイアウトがシフトし、Cumulative Layout Shiftスコアが0.493に跳ね上がりました。3

デバッグの経緯:LighthouseがCLSをフラグしました。DevToolsがシフトしている要素を特定しました。計算済みスタイルを検査すると、4pxを期待していた箇所でmargin-top: 0が表示されました。スタイルシートで--spacing-2xsを検索すると、使用が1箇所、定義が0箇所でした。

修正方法:--spacing-2xs--spacing-xsに変更しました。より根本的な修正:例外なくトークンシステムに厳格に従うことです。

タイポグラフィスケール

12pxから80pxまでの13段階、システムフォントを使用:

:root {
  --font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
                 "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
  --font-size-xs:      0.75rem;   /* 12px */
  --font-size-sm:      0.875rem;  /* 14px */
  --font-size-base:    1rem;      /* 16px */
  --font-size-lg:      1.125rem;  /* 18px */
  --font-size-xl:      1.3125rem; /* 21px */
  --font-size-2xl:     1.5625rem; /* 25px */
  --font-size-3xl:     1.875rem;  /* 30px */
  --font-size-4xl:     2.25rem;   /* 36px */
  --font-size-5xl:     2.7rem;    /* 43.2px */
  --font-size-6xl:     3.25rem;   /* 52px */
  --font-size-7xl:     3.875rem;  /* 62px */
  --font-size-display: 5rem;      /* 80px */
}

システムフォントはフォント読み込みのレイテンシーを完全に排除します。FOIT(Flash of Invisible Text)なし、FOUT(Flash of Unstyled Text)なし、フォントのためのネットワークリクエストはゼロです。この選択は、私のLighthouseパフォーマンススコア100/100に貢献しています。4


タイミングの問題

早すぎる場合:時期尚早な抽象化の罠

シード段階のスタートアップは、プロダクトが何になるかについて極めて高い不確実性に直面しています。デザインシステムはインタラクションパターン、コンポーネント階層、ビジュアル言語に関する前提を固定化します。プロダクトがピボットすると、デザインシステムは変化に抵抗する負債になります。5

3人のエンジニアと1人のデザイナーのチームには、ドキュメント、バージョニング、Storybookインスタンスを備えたコンポーネントライブラリは必要ありません。調整のオーバーヘッドが調整問題を上回ってしまいます。

しかし、トークンは異なります。トークンは抽象化ではなく、値です。カラートークンはコンポーネント構造を強制しません。スペーシングトークンはインタラクションパターンを制約しません。トークンはコンポーネント層の下位で機能するため、ピボットを乗り越えることができます。

遅すぎる場合:デザイン負債のスパイラル

30人のエンジニアを抱え、共有されたデザインパターンのないシリーズBの企業は、逆の問題に直面しています。各機能チームが独自のボタンスタイル、フォームレイアウト、スペーシング値を作り出します。プロダクトはまるで3つの異なるアプリケーションをつなぎ合わせたように感じられます。6

私は自分のプロジェクトでも、より小さな規模で同じパターンを目にしています。:rootトークンをコピーせずに新しいプロジェクトを始めると、最初の1週間以内に不整合が現れます。トークンは、巻き戻すのに高いコストがかかる負債スパイラルに対する、安価な保険です。


プログレッシブ投資フレームワーク

ステージ1:トークンのみ(初日、あらゆるチームサイズ)

基盤となる値のみを定義して共有します。私の実装:

トークンカテゴリ 目的
カラー 10 背景、テキスト、ボーダー、アクセント
タイポグラフィ 13 xsからdisplayまでのフォントサイズ
スペーシング 8 8px基準単位のスケール
ボーダーラディウス 4 sm(8px)、md(16px)、lg(32px)、xl(48px)
トランジション 3 fast(150ms)、base(300ms)、slow(600ms)
レイアウト 3 max-width narrow(800px)、default(1400px)、wide(1600px)

合計41トークン。コンポーネントはゼロ。ドキュメントサイトもゼロ。目標は、実験の最大限の柔軟性を維持しながら、値レベルでの乖離を防ぐことです。7

ステージ2:パターン抽出(パターンが3回繰り返されたとき)

同じUI要素が3つの異なる機能に登場したとき、パターンを抽出します。私のサイトで抽出されたパターンは以下の通りです: - カードレイアウト(プロジェクトカード、ブログカード、ソーシャルカード):一貫したpadding、border-radius、ホバーステート - ナビゲーションアンダーライン(ナビリンク、パンくずリスト):ホバー時のscaleX(0) → scaleX(1)トランジション - グラスモーフィズムヘッダーbackdrop-filter: blur(20px)とborder-bottom

各パターンは、同じものを3回構築し、重複に気づいたことで生まれました。事前にデザインするのではなく、本番コードからパターンを抽出します。本番パターンは実際の要件をエンコードしています。8

ステージ3:正式なシステム(25人以上のエンジニア、ソロプロジェクトでは決して)

スケールが大きくなると、調整問題がコンポーネントライブラリ、Figmaミラーリング、コントリビューションプロセス、バージョン管理されたチェンジログを正当化します。私は個人プロジェクトでこのステージに到達したことはなく、到達する予定もありません。ソロ開発者にとって、トークン+抽出されたパターンは、正式なシステムのメンテナンスオーバーヘッドなしに十分な構造を提供します。


完全にスキップしているもの

ドキュメントサイト

公開向けデザインシステムのドキュメントサイトは、ソロプロジェクトにおいてユーザー価値をゼロにするエンジニアリング時間を消費します。私の「ドキュメント」はcritical.css:rootブロックです。ファイルを読む開発者(またはAIエージェント)は、即座にシステムを理解できます。

マルチフレームワークサポート

私のサイトはプレーンCSSを使用しています。Reactコンポーネントも、Vueラッパーも、Web Componentsもありません。CSSカスタムプロパティはフレームワークに依存しないため、トークンはどのフレームワークでも機能します。抽象化レイヤーはCSS自体です。

時期尚早なアクセシビリティシアター

アクセシビリティは重要です——私のサイトはすべてのテキストティアでWCAG AAAコントラストを達成しています。しかし、まずコントラストシステム(既知の比率を持つトークン)を構築し、次にコンプライアンスを検証しました。組み込みのアクセシビリティを持つトークン(すべてのテキストティアが7:1のコントラスト比を超える)から始めることは、任意のカラー選択を後からオーディットするよりも効果的です。9


重要なポイント

ソロ開発者の方へ: - カラー、タイプ、スペーシング、トランジションのCSSカスタムプロパティを初日に定義しましょう。41トークンへの投資が、後でデバッグに何時間もかかるバグや不整合を防ぎます - コンポーネントライブラリ、ドキュメントサイト、Storybookはスキップしましょう。ソロプロジェクトでは、メンテナンスオーバーヘッドが調整の利益を上回ります - 同じ要素が3箇所に登場したとき、本番コードからパターンを抽出しましょう。時期尚早な抽出は、次のイテレーションで生き残れないかもしれないパターンに対する労力の無駄です

スタートアップのデザインリードの方へ: - プロダクトマーケットフィットの前にトークンから始めましょう。トークンはコンポーネント層の下位で機能するため、ピボットを乗り越えます - 25人以上のエンジニアが本当の調整問題を生み出すまで、正式なシステムには抵抗しましょう。そのしきい値に達する前の形式化は、イテレーションを遅くするメンテナンスオーバーヘッドを生み出します


参照


  1. 筆者のCLSデバッグ経験。未定義の--spacing-2xsトークンに起因するCumulative Layout Shift 0.493。MEMORY.mdのエラーエントリに記録。 

  2. 筆者のcritical.cssからのCSSカスタムプロパティ。10のカラートークン、すべて白地に黒の不透明度関係から導出。 

  3. 筆者のデバッグ経験。--spacing-2xsが使用されたが:rootで未定義。CSSカスタムプロパティはサイレントに失敗し、期待値の代わりにマージンゼロを生成。 

  4. 筆者のタイポグラフィシステム。13段階のフォントスケール、システムフォントスタック。フォント読み込みレイテンシーゼロがLighthouseパフォーマンス100/100に貢献。 

  5. Cagan, Marty, Inspired: How to Create Tech Products Customers Love, Wiley, 2017. プロダクトマーケットフィットと時期尚早な最適化。 

  6. Curtis, Nathan, “Adopting Design Systems,” EightShapes, 2018. スケーリング企業におけるデザイン負債の測定。 

  7. 筆者のトークンインベントリ。critical.cssで定義された6カテゴリにわたる41のCSSカスタムプロパティ。 

  8. Frost, Brad, Atomic Design, self-published, 2016. プログレッシブなコンポーネント抽象化手法。 

  9. 筆者のアクセシビリティアプローチ。トークン定義に組み込まれたWCAG AAAコントラスト(primary 21:1、secondary 13.7:1、tertiary 8.4:1)。