



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp








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



よーく聞くんだぞ!Tailwind CSSはデザインシステム構築に最適なんじゃ。今日はtailwind.config.jsの設定から、チーム運用のベストプラクティスまで詳しく解説するぞい!
結論から言うと、Tailwind CSSはtailwind.config.jsに色・フォント・余白などのデザイントークンを集約できるため、デザインシステムの基盤として最適です。適切な設計と運用ルールを設けることで、クラス名の乱立やスタイルの不統一を防ぎ、チームでの一貫した開発が実現します。
本記事では、Tailwind CSSを使ったデザインシステムの構築方法から、チーム開発での運用ベストプラクティスまで、実践的な実装例を交えて徹底的に解説します。
デザインシステムとは、デザインの一貫性を保つための、再利用可能なコンポーネントとガイドラインの集合体です。以下の要素で構成されます。
| メリット | 具体的な効果 |
|---|---|
| 開発速度の向上 | 既存コンポーネントを再利用できるため、ゼロから作る必要がない |
| 一貫性の確保 | 色やフォントサイズが統一され、ブランドイメージが保たれる |
| メンテナンス性 | 変更箇所が明確で、影響範囲を把握しやすい |
| オンボーディングの効率化 | 新メンバーが早く開発に参加できる |
| 品質向上 | アクセシビリティやレスポンシブ対応が標準化される |



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



まずは小さく始めるのがコツじゃ!デザイナーとエンジニアが協力して、基本的なデザイントークンから定義していくんじゃよ
デザインシステム構築の第一歩は、チーム全体での合意形成です。以下の項目について、デザイナーとエンジニアが一緒に決定します。
重要: この段階でFigmaのライブラリも同時に作成します。デザインツールの値とTailwind CSSの設定値を一致させることで、デザインとコードの乖離を防げます。
# 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を使い、デフォルトの便利な値は残しておくことをおすすめします。
色の命名規則は非常に重要です。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>テキストサイズはすべてパターン化して定義することで、運用が非常にしやすくなります。
// 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>// 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の拡張機能を使えば、カスタムクラスも自動補完してくれるんじゃよ
tailwind.config.jsで定義したカスタムクラスも含めて、すべてのクラス名を自動補完してくれる必須ツールです。VS Codeの拡張機能タブで「Tailwind CSS IntelliSense」を検索してインストールするだけで、クラス名の自動補完・ホバーでのCSS内容表示・リンティングが使えるようになります。
# インストール
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"
}
}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">tailwind.config.jsで定義した値は必ずそれを使い、ベタ書きは禁止することをコーディング規約に明記します。
<!-- ❌ 悪い例:ベタ書き -->
<div className="text-[18px] leading-[1.5] font-bold">
<!-- ✅ 良い例:定義済みクラスを使用 -->
<div className="text-title-lg">よく使うパターンは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># 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: 'アウトラインボタン',
},
}Primary/5、Tailwindではprimary-5のように対応関係を明確にする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;
}
}


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



その通りじゃ!最初の構築は大変じゃが、一度作ってしまえば開発スピードが格段に上がるんじゃ。まずは小さく始めて、徐々に拡充していくのがコツじゃぞ!
基本はtailwind.config.jsでデザイントークンを管理することをおすすめします。ただし、ダークモード対応やJavaScriptから動的に値を変えたい場合はCSS変数を併用するのが有効です。Tailwind v3以降は@layer base内でCSS変数を定義し、それをtailwind.config.jsから参照するパターンが一般的です。
できます。ただし、既存のCSSと競合しないよう段階的に導入することをおすすめします。まずtailwind.config.jsにデザイントークンのみを定義し、新規コンポーネントからTailwindクラスを使い始め、既存コンポーネントは随時リファクタリングする方法が現実的です。Tailwindのprefixオプションで既存クラスとの衝突を防ぐことも有効です。
条件分岐でクラスを動的に切り替えるReactコンポーネントを作る場合は、clsxやcnライブラリが非常に便利です。cnヘルパー(clsxとtailwind-mergeの組み合わせ)を使うと、競合するTailwindクラスを自動で解決してくれます。shadcn/uiのパターンとして広く採用されており、コンポーネント設計の標準的なアプローチです。
できます。tailwind.config.jsをパッケージとしてエクスポートし、使用するプロジェクト側でpresetとして読み込む方法が一般的です。presets: [require('@your-org/design-tokens')]のように指定するだけで、デザイントークンを複数プロジェクトで共有できます。複数サービスを持つ企業や、プロジェクト横断でのブランド統一に有効です。
はい、Tailwind CSS v4ではtailwind.config.jsに代わりCSSファイル内で@themeディレクティブを使ってデザイントークンを定義するアプローチに変わります。ただし、本質的な「デザイントークンを一元管理する」という考え方は変わりません。v4への移行時は公式の移行ガイドを参照し、既存の設定を段階的に移行することをおすすめします。



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


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