WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

【実践ガイド】Tailwind CSSデザインシステム運用の完全マニュアル!構築から運用まで実装例を踏まえて詳しく解説

目次

この記事でわかること

  • デザインシステムとは何か・Tailwind CSSが基盤として優れている理由
  • tailwind.config.jsでのカラー・タイポグラフィ・スペーシング・シャドウの定義方法
  • IntelliSense・ESLint・Prettierによる開発環境の整備手順
  • ベタ書き禁止ルール・コンポーネント化・Storybookによるチーム運用のベストプラクティス
  • Figmaとの連携フローと、デザイントークン変更時の保守ワークフロー
生徒

Tailwind CSSでデザインシステムを作りたいんですが、どうやって管理すれば良いでしょうか?

ペン博士

よーく聞くんだぞ!Tailwind CSSはデザインシステム構築に最適なんじゃ。今日はtailwind.config.jsの設定から、チーム運用のベストプラクティスまで詳しく解説するぞい!

結論から言うと、Tailwind CSSはtailwind.config.jsに色・フォント・余白などのデザイントークンを集約できるため、デザインシステムの基盤として最適です。適切な設計と運用ルールを設けることで、クラス名の乱立やスタイルの不統一を防ぎ、チームでの一貫した開発が実現します。

本記事では、Tailwind CSSを使ったデザインシステムの構築方法から、チーム開発での運用ベストプラクティスまで、実践的な実装例を交えて徹底的に解説します。


Tailwind CSSとデザインシステムの関係

デザインシステムとは?

デザインシステムとは、デザインの一貫性を保つための、再利用可能なコンポーネントとガイドラインの集合体です。以下の要素で構成されます。

  • デザイントークン:色、フォント、余白、角丸などの基本値
  • コンポーネント:ボタン、カード、フォームなどの再利用可能なUI部品
  • パターン:レイアウトやページ構成のテンプレート
  • ガイドライン:使用方法やルールの文書

Tailwind CSSがデザインシステムに適している5つの理由

  1. 設定ファイルでデザイントークンを一元管理:tailwind.config.jsで色・フォント・余白をすべて定義でき、変更時も一箇所を修正するだけで全体に反映されます
  2. 制約を持たせた自由度:デフォルトで用意された値を使うことでデザインの一貫性が保たれ、カスタマイズも柔軟に行えます
  3. デザイナーとエンジニアの共通言語:クラス名がそのままデザイントークン名になるため、コミュニケーションがスムーズになります
  4. メンテナンス性の高さ:ユーティリティクラスを組み合わせるため、CSSファイルが肥大化せず変更も局所的に行えます
  5. パフォーマンス最適化:未使用のCSSを自動削除するPurgeCSSが標準搭載されており、本番環境では最小限のCSSサイズになります

デザインシステムがもたらすメリット

メリット具体的な効果
開発速度の向上既存コンポーネントを再利用できるため、ゼロから作る必要がない
一貫性の確保色やフォントサイズが統一され、ブランドイメージが保たれる
メンテナンス性変更箇所が明確で、影響範囲を把握しやすい
オンボーディングの効率化新メンバーが早く開発に参加できる
品質向上アクセシビリティやレスポンシブ対応が標準化される

デザインシステムの構築ステップ

生徒

デザインシステムってどうやって作り始めれば良いんですか?

ペン博士

まずは小さく始めるのがコツじゃ!デザイナーとエンジニアが協力して、基本的なデザイントークンから定義していくんじゃよ

ステップ1:デザイナーとエンジニアで共通認識を持つ

デザインシステム構築の第一歩は、チーム全体での合意形成です。以下の項目について、デザイナーとエンジニアが一緒に決定します。

  • カラーパレット(プライマリー、セカンダリー、グレースケール、状態色など)
  • タイポグラフィ(フォントファミリー、サイズ、行間、ウェイト)
  • スペーシング(余白のパターン)
  • ボーダー(角丸、線の太さ)
  • シャドウ(影の種類と強度)
  • z-index(レイヤー構造)

重要: この段階でFigmaのライブラリも同時に作成します。デザインツールの値とTailwind CSSの設定値を一致させることで、デザインとコードの乖離を防げます。

ステップ2:tailwind.config.jsの基本設定

# Next.jsプロジェクトの作成(Tailwind CSS込み)
npx create-next-app@latest my-design-system --typescript --tailwind

# または既存プロジェクトにTailwind CSSをインストール
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      // ここにカスタム設定を追加
    },
  },
  plugins: [],
}

theme.extend vs theme の違い: theme.extendはデフォルト値を保持したまま追加値を定義します。themeはデフォルト値を完全に上書きします。通常はtheme.extendを使い、デフォルトの便利な値は残しておくことをおすすめします。


デザイントークンの定義と管理

1. カラーパレットの定義

色の命名規則は非常に重要です。Tailwindのデフォルト(gray-100など)と混同しないよう、独自の命名規則を採用します。

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        // プライマリーカラー
        primary: {
          1: '#E3F2FD', // 最も薄い
          2: '#BBDEFB',
          3: '#90CAF9',
          4: '#64B5F6',
          5: '#42A5F5', // 基本色
          6: '#2196F3',
          7: '#1E88E5',
          8: '#1976D2',
          9: '#1565C0', // 最も濃い
        },

        // セカンダリーカラー
        secondary: {
          1: '#F3E5F5',
          2: '#E1BEE7',
          3: '#CE93D8',
          4: '#BA68C8',
          5: '#AB47BC', // 基本色
          6: '#9C27B0',
          7: '#8E24AA',
          8: '#7B1FA2',
          9: '#6A1B9A',
        },

        // グレースケール(シンプルな命名)
        gray: {
          1: '#FAFAFA', // 背景用の薄いグレー
          2: '#F5F5F5',
          3: '#EEEEEE',
          4: '#E0E0E0',
          5: '#BDBDBD',
          6: '#9E9E9E',
          7: '#757575',
          8: '#616161',
          9: '#424242',
          10: '#212121', // テキスト用の濃いグレー
        },

        // 状態を表す色
        success: {
          light: '#C8E6C9',
          DEFAULT: '#4CAF50',
          dark: '#388E3C',
        },
        warning: {
          light: '#FFE082',
          DEFAULT: '#FFC107',
          dark: '#F57C00',
        },
        error: {
          light: '#FFCDD2',
          DEFAULT: '#F44336',
          dark: '#C62828',
        },
        info: {
          light: '#B3E5FC',
          DEFAULT: '#03A9F4',
          dark: '#0277BD',
        },
      },
    },
  },
}

カラーパレットの使用例

<!-- プライマリーカラーの使用 -->
<button className="bg-primary-5 hover:bg-primary-6 text-white">
  ボタン
</button>

<!-- グレースケールの使用 -->
<div className="bg-gray-1 border border-gray-4 text-gray-10">
  コンテンツ
</div>

<!-- 状態色の使用 -->
<div className="bg-success text-white">成功メッセージ</div>
<div className="bg-error text-white">エラーメッセージ</div>

2. タイポグラフィの定義

テキストサイズはすべてパターン化して定義することで、運用が非常にしやすくなります

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        // 基本フォント
        sans: [
          'Noto Sans JP',
          'Hiragino Sans',
          'Hiragino Kaku Gothic ProN',
          'Arial',
          'sans-serif',
        ],
        // コード用フォント
        mono: [
          'Fira Code',
          'Consolas',
          'Monaco',
          'Courier New',
          'monospace',
        ],
        // 特殊なフォント(見出し専用など)
        display: ['Montserrat', 'sans-serif'],
      },
      fontSize: {
        // [サイズ, { lineHeight, letterSpacing, fontWeight }]

        // 見出し
        'heading-xl': ['48px', { lineHeight: '1.2', fontWeight: '700' }],
        'heading-lg': ['36px', { lineHeight: '1.3', fontWeight: '700' }],
        'heading-md': ['28px', { lineHeight: '1.4', fontWeight: '700' }],
        'heading-sm': ['24px', { lineHeight: '1.4', fontWeight: '700' }],

        // タイトル
        'title-xl': ['20px', { lineHeight: '1.5', fontWeight: '700' }],
        'title-lg': ['18px', { lineHeight: '1.5', fontWeight: '700' }],
        'title-md': ['16px', { lineHeight: '1.5', fontWeight: '700' }],
        'title-sm': ['14px', { lineHeight: '1.5', fontWeight: '700' }],

        // 本文
        'body-lg': ['16px', { lineHeight: '1.7', fontWeight: '400' }],
        'body-md': ['14px', { lineHeight: '1.7', fontWeight: '400' }],
        'body-sm': ['12px', { lineHeight: '1.7', fontWeight: '400' }],

        // キャプション
        'caption-md': ['12px', { lineHeight: '1.5', fontWeight: '400' }],
        'caption-sm': ['10px', { lineHeight: '1.5', fontWeight: '400' }],
      },
    },
  },
}

タイポグラフィの使用例

<h1 className="text-heading-xl text-gray-10">
  大見出し
</h1>

<h2 className="text-heading-lg text-gray-10">
  中見出し
</h2>

<h3 className="text-title-lg text-gray-9">
  小見出し
</h3>

<p className="text-body-md text-gray-8">
  本文のテキストです。行間や文字サイズが自動的に適用されます。
</p>

<p className="text-caption-md text-gray-6">
  補足説明やキャプション
</p>

3. スペーシング・シャドウ・その他の定義

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        // セクション間の余白
        'section-sm': '40px',
        'section-md': '60px',
        'section-lg': '80px',
        'section-xl': '120px',

        // コンテナの余白
        'container-sm': '16px',
        'container-md': '24px',
        'container-lg': '32px',

        // カード内の余白
        'card-sm': '12px',
        'card-md': '16px',
        'card-lg': '24px',
      },
      // ボックスシャドウ
      boxShadow: {
        'card-sm': '0 1px 3px rgba(0, 0, 0, 0.12)',
        'card-md': '0 4px 6px rgba(0, 0, 0, 0.1)',
        'card-lg': '0 10px 20px rgba(0, 0, 0, 0.15)',
        'card-xl': '0 20px 40px rgba(0, 0, 0, 0.2)',
        'floating': '0 8px 16px rgba(0, 0, 0, 0.15)',
      },
      // 角丸
      borderRadius: {
        'card': '8px',
        'button': '6px',
        'input': '4px',
        'modal': '12px',
      },
      // z-index(レイヤー管理)
      zIndex: {
        'dropdown': '1000',
        'sticky': '1020',
        'fixed': '1030',
        'modal-backdrop': '1040',
        'modal': '1050',
        'popover': '1060',
        'tooltip': '1070',
      },
      // アニメーション
      transitionDuration: {
        'fast': '150ms',
        'normal': '250ms',
        'slow': '350ms',
      },
      // ブレークポイント
      screens: {
        'xs': '375px',
        'sm': '640px',
        'md': '768px',
        'lg': '1024px',
        'xl': '1280px',
        '2xl': '1536px',
      },
    },
  },
}

開発効率を上げるツール設定

生徒

設定ファイルが大きくなると、クラス名を覚えるのが大変そうです…

ペン博士

心配ご無用じゃ!VS Codeの拡張機能を使えば、カスタムクラスも自動補完してくれるんじゃよ

1. Tailwind CSS IntelliSense(VS Code拡張機能)

tailwind.config.jsで定義したカスタムクラスも含めて、すべてのクラス名を自動補完してくれる必須ツールです。VS Codeの拡張機能タブで「Tailwind CSS IntelliSense」を検索してインストールするだけで、クラス名の自動補完・ホバーでのCSS内容表示・リンティングが使えるようになります。

2. eslint-plugin-tailwindcss

# インストール
npm install -D eslint-plugin-tailwindcss

# .eslintrc.json に追加
{
  "extends": [
    "next/core-web-vitals",
    "plugin:tailwindcss/recommended"
  ],
  "rules": {
    "tailwindcss/classnames-order": "warn",
    "tailwindcss/no-custom-classname": "warn",
    "tailwindcss/no-contradicting-classname": "error"
  }
}

3. prettier-plugin-tailwindcss

Tailwind CSSのクラス名を、公式の推奨順序に自動で並べ替えてくれるPrettierプラグインです。

# インストール
npm install -D prettier prettier-plugin-tailwindcss

# .prettierrc.json を作成
{
  "plugins": ["prettier-plugin-tailwindcss"],
  "semi": false,
  "singleQuote": true,
  "trailingComma": "es5"
}
<!-- Before(整理されていない順序) -->
<div className="text-white p-4 bg-primary-5 rounded-lg shadow-md hover:bg-primary-6">

<!-- After(自動整理後) -->
<div className="rounded-lg bg-primary-5 p-4 text-white shadow-md hover:bg-primary-6">

チーム運用のベストプラクティス

1. ベタ書き禁止ルール

tailwind.config.jsで定義した値は必ずそれを使い、ベタ書きは禁止することをコーディング規約に明記します。

<!-- ❌ 悪い例:ベタ書き -->
<div className="text-[18px] leading-[1.5] font-bold">

<!-- ✅ 良い例:定義済みクラスを使用 -->
<div className="text-title-lg">

2. コンポーネント化の推進

よく使うパターンはReactコンポーネントとして抽出します。

// components/Button.tsx
type ButtonProps = {
  variant?: 'primary' | 'secondary' | 'outline'
  size?: 'sm' | 'md' | 'lg'
  children: React.ReactNode
  onClick?: () => void
}

export function Button({
  variant = 'primary',
  size = 'md',
  children,
  onClick,
}: ButtonProps) {
  const baseClasses = 'rounded-button font-semibold transition-fast'

  const variantClasses = {
    primary: 'bg-primary-5 hover:bg-primary-6 text-white',
    secondary: 'bg-secondary-5 hover:bg-secondary-6 text-white',
    outline: 'border-2 border-primary-5 text-primary-5 hover:bg-primary-1',
  }

  const sizeClasses = {
    sm: 'px-4 py-2 text-body-sm',
    md: 'px-6 py-3 text-body-md',
    lg: 'px-8 py-4 text-body-lg',
  }

  return (
    <button
      className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
      onClick={onClick}
    >
      {children}
    </button>
  )
}

// 使用例
<Button variant="primary" size="md">送信</Button>
<Button variant="outline" size="sm">キャンセル</Button>

3. Storybookでコンポーネントカタログを整備する

# Storybookのインストール
npx storybook@latest init

# components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'

const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
  tags: ['autodocs'],
}

export default meta
type Story = StoryObj<typeof Button>

export const Primary: Story = {
  args: {
    variant: 'primary',
    children: 'プライマリーボタン',
  },
}

export const Secondary: Story = {
  args: {
    variant: 'secondary',
    children: 'セカンダリーボタン',
  },
}

export const Outline: Story = {
  args: {
    variant: 'outline',
    children: 'アウトラインボタン',
  },
}

4. Figmaとの連携

  1. Figmaでデザイントークンを定義:カラースタイル・テキストスタイル・エフェクトスタイル(シャドウ)を設定する
  2. 命名規則を統一する:FigmaではPrimary/5、Tailwindではprimary-5のように対応関係を明確にする
  3. Figma Tokensプラグインを活用:FigmaのデザイントークンをJSONで出力し、tailwind.config.jsに変換できる

実践的なディレクトリ構成とグローバルスタイル

my-project/
├── tailwind.config.js          # デザイントークン定義
├── src/
│   ├── styles/
│   │   ├── globals.css         # グローバルスタイル
│   │   └── components.css      # カスタムコンポーネントスタイル
│   │
│   ├── components/
│   │   ├── ui/                 # 基本UIコンポーネント
│   │   │   ├── Button.tsx
│   │   │   ├── Button.stories.tsx
│   │   │   ├── Input.tsx
│   │   │   ├── Card.tsx
│   │   │   └── Modal.tsx
│   │   │
│   │   ├── layout/             # レイアウトコンポーネント
│   │   │   ├── Header.tsx
│   │   │   ├── Footer.tsx
│   │   │   └── Container.tsx
│   │   │
│   │   └── features/           # 機能別コンポーネント
│   │       ├── auth/
│   │       └── dashboard/
│   │
│   └── lib/
│       ├── utils.ts            # ユーティリティ関数
│       └── cn.ts               # クラス名結合ヘルパー
│
└── docs/
    ├── design-system.md        # デザインシステムガイド
    └── coding-guidelines.md    # コーディング規約
/* src/styles/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  /* フォントの一括適用 */
  body {
    @apply font-sans text-body-md text-gray-10;
  }

  /* 見出しのデフォルトスタイル */
  h1 {
    @apply text-heading-xl text-gray-10;
  }

  h2 {
    @apply text-heading-lg text-gray-10;
  }

  h3 {
    @apply text-heading-md text-gray-10;
  }
}

@layer components {
  /* よく使うパターンをコンポーネント化 */
  .btn {
    @apply rounded-button px-6 py-3 font-semibold transition-fast;
  }

  .btn-primary {
    @apply btn bg-primary-5 text-white hover:bg-primary-6;
  }

  .card {
    @apply rounded-card bg-white p-card-md shadow-card-md;
  }
}

保守・更新のワークフロー

デザイントークンの変更フロー

  1. デザイナーがFigmaで変更:カラーやフォントサイズの変更を提案
  2. チームでレビュー:変更の影響範囲を確認し、合意形成
  3. tailwind.config.jsを更新:エンジニアが設定ファイルを更新
  4. 影響箇所を確認:変更がどのコンポーネントに影響するか確認
  5. テスト・レビュー:ビジュアルリグレッションテストなどで確認
  6. デプロイ:本番環境に反映

新しいコンポーネントの追加フロー

  1. デザイナーがFigmaでコンポーネントを作成
  2. エンジニアがReactコンポーネントとして実装
  3. Storybookにドキュメントを追加
  4. レビュー・承認
  5. コンポーネントライブラリに追加

生徒

デザインシステムを作ることで、開発がこんなに効率的になるんですね!

ペン博士

その通りじゃ!最初の構築は大変じゃが、一度作ってしまえば開発スピードが格段に上がるんじゃ。まずは小さく始めて、徐々に拡充していくのがコツじゃぞ!


よくある質問

tailwind.config.jsとCSSのカスタムプロパティ(CSS変数)はどちらを使うべきですか?

基本はtailwind.config.jsでデザイントークンを管理することをおすすめします。ただし、ダークモード対応やJavaScriptから動的に値を変えたい場合はCSS変数を併用するのが有効です。Tailwind v3以降は@layer base内でCSS変数を定義し、それをtailwind.config.jsから参照するパターンが一般的です。

既存プロジェクトにTailwind CSSのデザインシステムを後から導入できますか?

できます。ただし、既存のCSSと競合しないよう段階的に導入することをおすすめします。まずtailwind.config.jsにデザイントークンのみを定義し、新規コンポーネントからTailwindクラスを使い始め、既存コンポーネントは随時リファクタリングする方法が現実的です。Tailwindのprefixオプションで既存クラスとの衝突を防ぐことも有効です。

clsx・cn(classnames)ライブラリとTailwind CSSの組み合わせは必要ですか?

条件分岐でクラスを動的に切り替えるReactコンポーネントを作る場合は、clsxやcnライブラリが非常に便利です。cnヘルパー(clsxtailwind-mergeの組み合わせ)を使うと、競合するTailwindクラスを自動で解決してくれます。shadcn/uiのパターンとして広く採用されており、コンポーネント設計の標準的なアプローチです。

デザインシステムをNPMパッケージとして公開・共有できますか?

できます。tailwind.config.jsをパッケージとしてエクスポートし、使用するプロジェクト側でpresetとして読み込む方法が一般的です。presets: [require('@your-org/design-tokens')]のように指定するだけで、デザイントークンを複数プロジェクトで共有できます。複数サービスを持つ企業や、プロジェクト横断でのブランド統一に有効です。

Tailwind CSS v4ではデザインシステムの管理方法は変わりますか?

はい、Tailwind CSS v4ではtailwind.config.jsに代わりCSSファイル内で@themeディレクティブを使ってデザイントークンを定義するアプローチに変わります。ただし、本質的な「デザイントークンを一元管理する」という考え方は変わりません。v4への移行時は公式の移行ガイドを参照し、既存の設定を段階的に移行することをおすすめします。


まとめ

生徒

わかりました!チームで相談して、デザインシステムを作ってみます!

  • tailwind.config.jsがデザインシステムの核:色・フォント・余白・シャドウなどすべてのデザイントークンを一元管理する
  • デザイナーとエンジニアで命名規則を統一する:FigmaとTailwindの値を対応させることでデザインとコードの乖離を防ぐ
  • IntelliSense・ESLint・Prettierを整備する:ツールによる補完・検証・フォーマットで開発効率と品質を両立する
  • ベタ書き禁止・コンポーネント化を徹底する:コーディング規約に明記し、チーム全体で運用する
  • Storybookでコンポーネントカタログを整備する:新メンバーのオンボーディングと既存コンポーネントの発見可能性が向上する
  • 変更フローを明確にして継続的に改善する:デザイン変更→レビュー→設定更新→テスト→デプロイのフローを文書化する

WithCodeで学んだWeb制作の基礎知識に、Tailwind CSSのデザインシステムを組み合わせれば、大規模で保守性の高いプロジェクトを効率的に開発できます。デザインシステムは一度作れば終わりではなく、プロジェクトの成長とともに進化させていくものです。まずは小さく始めて、チーム全体で育てていくことが成功の鍵です。


WithCodeを体験できる初級コース公開中!

WithCode初級コース

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    → 正しい学習方法で「確かな成長」を実感できるカリキュラム

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?未経験でも心配することはありません。まずは無料カウンセリングで、悩みや不安をお聞かせください!

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら
  • WithCareer
    - ウィズキャリ -

    就転職サポート

    大手エージェントのサポート下で
    キャリアアップを目指そう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次