dev TailwindCSS

Tailwind CSS ユーティリティクラスによるスタイリング完全ガイド - Overview & Why not inline styles 編

Tailwind CSSの基本概念「ユーティリティクラス」の仕組みと利点を実践的に学びます。従来のCSSとの違い、インラインスタイルとの比較、そして実際のコード例を通じて、なぜTailwind CSSが生産性と保守性を向上させるのかを理解できます。

読者がこの記事から得られる知識

この記事では、Tailwind CSS utility classes(ユーティリティクラス)の基本概念を実践的に学びます。公式ドキュメントの「Styling with utility classes」のOverviewセクションとWhy not inline stylesセクションを実際に手を動かしながら学習した内容をまとめています。

Tailwind CSSを初めて学ぶ方でも、従来のCSSアプローチとの違いを明確に理解でき、すぐに実践できる知識が得られます。

得られる知識は以下の通りです。

  • Tailwind CSSのユーティリティクラスによるスタイリングの基本概念と従来のCSSとの違い
  • インラインスタイルとユーティリティクラスの本質的な3つの違い(デザインシステム、状態管理、レスポンシブ対応)
  • レスポンシブバリアント(sm:、md:など)とhoverバリアントの仕組みと実践的な使い方
  • ユーティリティクラスをコンポーネント化して再利用する3つの方法

この記事を読み終えることで、Tailwind CSSがなぜ多くの開発者に支持されているのか、その理由を体験的に理解できるようになります。また、実際にコードを書きながら学ぶことで、すぐにプロジェクトで活用できる実践的なスキルが身につきます。

今回ハンズオンした内容

今回は、Tailwind CSS公式ドキュメントの「Styling with utility classes - Overview」セクション(https://tailwindcss.com/docs/styling-with-utility-classes#overview)と「Why not just use inline styles?」セクションを参照し、ユーティリティクラスの基本概念と利点を実際に手を動かして学習しました。

CSS フレームワーク、npm パッケージ インストール、watch モード 自動ビルドといった実践的な技術を組み合わせながら、Tailwind CSSの本質的な考え方を理解していきます。

プロジェクト構造

tailwindcss/
├── node_modules/
├── src/
│   ├── index.html
│   ├── input.css
│   └── output.css
├── .gitignore
├── package.json
├── package-lock.json
├── LICENSE
└── README.md

ステップ1: HTMLファイルにChitChatカードを追加

実行する操作

VSCodeで src/index.html を開いて、以下のように編集します。

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="./output.css" rel="stylesheet">
</head>
<body class="bg-gray-100 p-8">
  <h1 class="text-3xl font-bold underline mb-8">
    Hello world!
  </h1>

  <!-- Overview サンプル: ChitChat カード -->
  <div class="mx-auto flex max-w-sm items-center gap-x-4 rounded-xl bg-white p-6 shadow-lg outline outline-black/5 dark:bg-slate-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10">
    <img class="size-12 shrink-0" src="https://via.placeholder.com/48x48/3b82f6/ffffff?text=CC" alt="ChitChat Logo" />
    <div>
      <div class="text-xl font-medium text-black dark:text-white">ChitChat</div>
      <p class="text-gray-500 dark:text-gray-400">You have a new message!</p>
    </div>
  </div>

</body>
</html>

操作の意味

Tailwind CSS公式ドキュメントのOverviewセクションで紹介されている「ChitChatカード」のサンプルコードを追加しています。このコードは、ユーティリティクラスを組み合わせてカードUIを構築する典型的な例です。

操作を実行する意図

Tailwind CSSの最も基本的な使い方である「HTMLに直接ユーティリティクラスを記述してスタイリングする」アプローチを実際に体験するためです。従来のCSSのように別ファイルでクラスを定義するのではなく、HTMLに直接スタイルを記述する方法を学びます。

実行結果

HTMLファイルが編集され、body要素に背景色とパディングが追加され、ChitChatカードが挿入されました。

実行結果の解説

ファイルが正常に編集されました。このHTMLコードには、以下のような特徴的なユーティリティクラスが含まれています。

  • bg-gray-100 p-8: body要素に背景色とパディングを設定
  • mx-auto flex max-w-sm: カードを中央配置し、最大幅を制限
  • rounded-xl bg-white p-6 shadow-lg: カードに角丸、白背景、パディング、影を設定
  • text-xl font-medium: テキストサイズとフォントウェイトを設定

それぞれのクラスが単一のCSSプロパティに対応しており、これらを組み合わせることで複雑なデザインを実現しています。

HTMLファイルの編集が完了しました。次はTailwind CSSをビルドして、ブラウザで確認します。

ステップ2: Tailwind CSSをwatch モードで起動

実行するコマンド

$ npm run dev

コマンドの意味

package.jsonに定義されているdevスクリプトを実行します。このスクリプトは以下の内容です。

"dev": "npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch"
  • @tailwindcss/cli: Tailwind CSSのコマンドラインツール
  • -i ./src/input.css: 入力ファイル(Tailwindディレクティブを含む)
  • -o ./src/output.css: 出力ファイル(コンパイルされたCSS)
  • --watch: ファイル変更を監視して自動的に再ビルド

コマンドを実行する意図

HTMLファイルで使用しているユーティリティクラスを検出し、必要なCSSだけを生成するためです。watch モードで起動することで、HTMLを編集するたびに自動的にCSSが再生成され、開発効率が向上します。

実行結果

ターミナルでコマンドを実行すると、Tailwind CSSがバックグラウンドで動作し始めます。src/output.cssファイルが生成または更新され、HTMLで使用されているユーティリティクラスに対応するCSSが出力されます。

実行結果の解説

Tailwind CSSは、HTMLファイルをスキャンして使用されているクラス名を検出し、それに対応するCSSだけを生成します。これにより、使用していないスタイルは出力されず、最終的なCSSファイルサイズが最小限に抑えられます。

watch モードで起動しているため、HTMLファイルを編集すると自動的にCSSが再ビルドされます。開発中はこのコマンドを起動したままにしておくと便利ですよ。

Tailwind CSSのビルドが完了しました。次はブラウザでHTMLファイルを開いて、実際の表示を確認しましょう。

ステップ3: ブラウザで表示確認

実行する操作

ブラウザで http://127.0.0.1:5500/src/index.html を開き、表示を確認します。

操作の意味

Live Serverなどの開発サーバーを使用して、作成したHTMLファイルをブラウザで表示します。

操作を実行する意図

Tailwind CSSのユーティリティクラスが正しく適用され、意図したデザインが表示されるかを視覚的に確認するためです。

実行結果

ブラウザには以下のような表示がされます。

  • 背景全体が薄いグレー(bg-gray-100
  • 中央に白いカードが表示(bg-white
  • カードには角丸(rounded-xl)と影(shadow-lg)が適用
  • カード内にロゴ画像とテキストが横並びで配置(flex items-center
  • テキストには適切なサイズと色が設定

実行結果の解説

Tailwind CSSのユーティリティクラスが正しく適用され、公式ドキュメントで紹介されているChitChatカードと同じデザインが表示されました。

重要なポイントは、CSSファイルを一切編集していないという点です。HTMLにユーティリティクラスを記述するだけで、以下のようなスタイリングが実現できています。

  • レイアウト制御(flex, items-center, gap-x-4
  • サイズ制御(max-w-sm, size-12
  • 色の設定(bg-white, text-black, text-gray-500
  • 装飾(rounded-xl, shadow-lg
  • ダークモード対応(dark:bg-slate-800, dark:text-white

これが、Tailwind CSSの「ユーティリティファーストCSS」と呼ばれるアプローチの実例ですね。

ブラウザでの表示確認が完了しました。Tailwind CSSのユーティリティクラスによるスタイリングの基本が理解できましたね。

ステップ4: レスポンシブなプロフィールカードを追加(Why not inline styles)

実行する操作

VSCodeで src/index.html を開いて、ChitChatカードの下に以下のコードを追加します。

<!-- Overview サンプル: ChitChat カード -->
  <div class="mx-auto flex max-w-sm items-center gap-x-4 rounded-xl bg-white p-6 shadow-lg outline outline-black/5 dark:bg-slate-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10">
    <img class="size-12 shrink-0" src="https://via.placeholder.com/48x48/3b82f6/ffffff?text=CC" alt="ChitChat Logo" />
    <div>
      <div class="text-xl font-medium text-black dark:text-white">ChitChat</div>
      <p class="text-gray-500 dark:text-gray-400">You have a new message!</p>
    </div>
  </div>

  <!-- ↓ ここから追加 -->
  <!-- Why not inline styles サンプル: レスポンシブなプロフィールカード -->
  <div class="mt-8 mx-auto max-w-sm">
    <div class="flex flex-col gap-2 p-8 sm:flex-row sm:items-center sm:gap-6 sm:py-4 bg-white rounded-xl shadow-lg">
      <img class="mx-auto block h-24 rounded-full sm:mx-0 sm:shrink-0" src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
      <div class="space-y-2 text-center sm:text-left">
        <div class="space-y-0.5">
          <p class="text-lg font-semibold text-black">Erin Lindford</p>
          <p class="font-medium text-gray-500">Product Engineer</p>
        </div>
        <button class="px-4 py-1 border border-purple-200 text-sm text-purple-600 font-semibold rounded-full hover:border-transparent hover:bg-purple-600 hover:text-white active:bg-purple-700">
          Message
        </button>
      </div>
    </div>
  </div>
  <!-- ↑ ここまで追加 -->

</body>
</html>

操作の意味

公式ドキュメントの「Why not just use inline styles?」セクションで紹介されている、レスポンシブなプロフィールカードのサンプルコードを追加しています。このコードには、以下の特徴があります。

  • レスポンシブレイアウト: 画面サイズによって縦並び/横並びが切り替わる
  • hover状態: ボタンにマウスを乗せると色が変わる
  • active状態: ボタンをクリック中は色がさらに変わる

操作を実行する意図

インラインスタイルでは実現できない、Tailwind CSSの3つの重要な機能を実際に体験するためです。

  1. メディアクエリ(レスポンシブデザイン)
  2. 疑似クラス(hover、active状態)
  3. デザインシステムによる一貫性

これらの機能が、なぜユーティリティクラスの方が優れているのかを理解します。

実行結果

HTMLファイルが編集され、ChitChatカードの下にプロフィールカードが追加されました。npm run dev が起動している状態であれば、ブラウザをリロードすると自動的に反映されます。

ブラウザで確認すると、以下のような表示になります。

  • デスクトップサイズ(640px以上): プロフィール画像とテキストが横並び
  • モバイルサイズ(640px未満): プロフィール画像とテキストが縦並び

実行結果の解説

プロフィールカードが正しく表示されました。このカードには、以下のようなレスポンシブクラスが含まれています。

  • flex-col: デフォルトで縦並び
  • sm:flex-row: 640px以上で横並びに変更
  • mx-auto: デフォルトで画像を中央配置
  • sm:mx-0: 640px以上で画像を左寄せに変更
  • text-center: デフォルトでテキストを中央揃え
  • sm:text-left: 640px以上でテキストを左揃えに変更

これらのクラスにより、画面サイズに応じて自動的にレイアウトが切り替わります。インラインスタイル(style 属性)では、このような条件分岐を書くことはできませんね。

プロフィールカードの追加が完了しました。次は、レスポンシブ動作を実際に確認してみましょう。

ステップ5: レスポンシブ動作とhover状態を確認

実行する操作

Chrome開発者ツール(F12)を開いて、以下の操作を行います。

  1. レスポンシブモードに切り替え(Ctrl + Shift + M)
  2. 画面サイズを変更して、レイアウトの変化を確認
  • デスクトップサイズ(1709px): 横並び
  • モバイルサイズ(600px): 縦並び
  1. Messageボタンにマウスを乗せて、色の変化を確認

操作の意味

Chrome開発者ツールのレスポンシブモードは、異なる画面サイズでの表示を簡単に確認できる機能です。実際にスマートフォンやタブレットを用意しなくても、様々なデバイスでの表示をシミュレートできます。

操作を実行する意図

Tailwind CSSのレスポンシブバリアント(sm:md: など)が実際にどのように動作するのかを視覚的に確認するためです。また、hover状態も実際に体験することで、インラインスタイルでは実現できない機能を理解します。

実行結果

画面サイズを変更すると、以下のように表示が切り替わります。

モバイルサイズ(600px)では:

  • プロフィール画像が上部中央に配置
  • テキストが中央揃え
  • ボタンも中央に配置

デスクトップサイズ(1709px)では:

  • プロフィール画像が左側に配置
  • テキストが左揃え
  • ボタンも左側に配置

Messageボタンにマウスを乗せると:

  • 背景が紫色に変化(hover:bg-purple-600
  • テキストが白色に変化(hover:text-white
  • 枠線が透明に変化(hover:border-transparent

実行結果の解説

Tailwind CSSのレスポンシブバリアントとhoverバリアントが正しく動作していることが確認できました。

レスポンシブの仕組み:

  • sm: プレフィックスは、@media (min-width: 640px) に相当します
  • デフォルト(640px未満)のスタイルをまず適用し、640px以上になると sm: のスタイルで上書きします
  • これは「モバイルファースト」と呼ばれるアプローチです

hoverの仕組み:

  • hover: プレフィックスは、:hover 疑似クラスに相当します
  • マウスを乗せたときだけスタイルが適用されます
  • インラインスタイル(style 属性)では、疑似クラスを使用できないため、このような動作は実現できません

これらの機能が、「Why not just use inline styles?」セクションで説明されている、ユーティリティクラスの3つの利点です。

  1. デザインシステムによる一貫性(定義された色、サイズから選択)
  2. 状態管理(hover、focus、activeなど)
  3. レスポンシブデザイン(メディアクエリ)

レスポンシブ動作とhover状態の確認が完了しました。これで、「Overview」と「Why not inline styles」の2セクションの学習が完了しましたね。

ハンズオンの中で私が疑問に感じた点や失敗した点

実際に疑問に感じた点

疑問1: このセクションで公式が伝えたかったことは何だったのか?

単にユーティリティクラスの使い方を示すだけではなく、もっと本質的なメッセージがあるように感じました。

解決手段

公式ドキュメントのOverviewセクションを改めて整理すると、以下の3つの核心的なメッセージがありました。

1点目: Tailwind CSSの基本的なアプローチ

従来のCSSでは、クラス名を定義してからCSSファイルでスタイルを記述していました。

<div class="card">
  <h2 class="card-title">ChitChat</h2>
</div>
.card {
  background-color: white;
  border-radius: 0.75rem;
  padding: 1.5rem;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}

Tailwind CSSでは、HTMLに直接ユーティリティクラスを記述します。

<div class="bg-white rounded-xl p-6 shadow-lg">
  <h2 class="text-xl font-medium">ChitChat</h2>
</div>

つまり、CSSファイルを書かずに、HTMLだけでスタイリングが完結します。

2点目: この方法の5つの具体的な利点

公式が強調していた利点は以下の通りです。

  • 作業が速くなる: クラス名を考える時間が不要で、HTMLとCSSファイルを行き来する必要がない
  • 変更がより安全になる: 1つの要素のスタイルを変更しても他のページに影響しない
  • 保守が簡単になる: 6ヶ月前に書いたカスタムCSSを思い出す必要がなく、HTMLを見ればスタイルがすぐわかる
  • コードがポータブルになる: HTML要素をコピー&ペーストするだけでスタイルごと移植できる
  • CSSが増え続けない: ユーティリティクラスは再利用可能なため、新機能を追加してもCSSファイルのサイズが増えない

3点目: Tailwind CSSの哲学

公式が伝えたかった本質的なメッセージは、「従来のベストプラクティスに反しているように見えるが、実際に試してみると驚くほど生産性が高く保守しやすいコードが書ける」ということです。

この整理により、Overviewセクションが単なる技術紹介ではなく、Tailwind CSSの設計思想と価値提案を伝えるセクションだったことが理解できました。

疑問2: max-w-sm など理解できていない部分があるが、ここで学習すべきか?

HTMLコードに含まれる max-w-sm, gap-x-4, shrink-0 などの個別のユーティリティクラスの詳細な意味がわからず、理解が不十分な状態で次に進んで良いのか不安を感じました。

解決手段

Overviewセクションで重要なのは、個別のクラスの詳細ではなく、Tailwind CSSの基本的なアプローチと利点を理解することです。

理解すべきこと:

  • Tailwind CSSの基本的なアプローチ(HTMLにユーティリティクラスを書く)
  • この方法の5つの利点
  • インラインスタイルとの違い

今は気にしなくて良いこと:

  • 個別のクラスの詳細(max-w-sm, gap-x-4, shrink-0 など)
  • クラスの命名規則の詳細
  • 各プロパティの値の意味

これらの詳細は、公式ドキュメントの他のセクション(Layout、Spacing、Sizingなど)で学習することになります。Overviewでは全体像を掴むことに集中し、細部は後で学ぶという学習戦略が適切です。

疑問3: 今回記述した class の内容についても別名をつけて保存しておけば他の部品(コンポーネント?)にも同じデザインを適用できるのか?

プロフィールカードのような複雑なスタイルのセットを、別名をつけて保存して再利用できるのか疑問に感じました。

解決手段

はい、可能です。Tailwind CSSでコンポーネント化する方法は、主に3つあります。

方法1: React/Vue などのコンポーネントフレームワークを使う(推奨)

Reactの例:

// ProfileCard.jsx
export function ProfileCard({ name, title, imageUrl }) {
  return (
    <div className="flex flex-col gap-2 p-8 sm:flex-row sm:items-center sm:gap-6 sm:py-4 bg-white rounded-xl shadow-lg">
      <img className="mx-auto block h-24 rounded-full sm:mx-0 sm:shrink-0" src={imageUrl} alt="" />
      <div className="space-y-2 text-center sm:text-left">
        <div className="space-y-0.5">
          <p className="text-lg font-semibold text-black">{name}</p>
          <p className="font-medium text-gray-500">{title}</p>
        </div>
        <button className="px-4 py-1 border border-purple-200 text-sm text-purple-600 font-semibold rounded-full hover:border-transparent hover:bg-purple-600 hover:text-white">
          Message
        </button>
      </div>
    </div>
  );
}

使用例:

<ProfileCard name="Erin Lindford" title="Product Engineer" imageUrl="..." />
<ProfileCard name="John Doe" title="Designer" imageUrl="..." />

メリット: 一度定義すれば何度でも簡単に再利用でき、データ(名前、タイトル、画像)を動的に渡せます。

方法2: カスタム CSS クラスを定義する

input.cssに追加:

@import "tailwindcss";

@layer components {
  .profile-card {
    @apply flex flex-col gap-2 p-8 sm:flex-row sm:items-center sm:gap-6 sm:py-4 bg-white rounded-xl shadow-lg;
  }

  .profile-card-image {
    @apply mx-auto block h-24 rounded-full sm:mx-0 sm:shrink-0;
  }

  .profile-card-button {
    @apply px-4 py-1 border border-purple-200 text-sm text-purple-600 font-semibold rounded-full hover:border-transparent hover:bg-purple-600 hover:text-white;
  }
}

HTMLでの使用:

<div class="profile-card">
  <img class="profile-card-image" src="..." alt="" />
  <div>
    <p>Erin Lindford</p>
    <p>Product Engineer</p>
    <button class="profile-card-button">Message</button>
  </div>
</div>

メリット: シンプルなHTMLで使えます。複雑なスタイルをまとめられます。

デメリット: データ(名前、タイトル)は手動で書く必要があります。

方法3: テンプレートパーシャル(静的サイトの場合)

ERB、Twig、Nunjucksなどのテンプレートエンジンを使う方法です。

公式の推奨順序:

  1. まずはループで対応できないか考える
  2. コンポーネントフレームワーク(React/Vue)を使う
  3. それでもダメなら、カスタムCSSクラスを定義

この解説により、ユーティリティクラスのセットをコンポーネント化して再利用する方法が理解できました。

よくある疑問

疑問1: ユーティリティクラスだとHTMLが長くなりすぎませんか?

確かに、1つの要素に10個以上のクラスが並ぶこともあります。

解決手段

HTMLが長くなることは事実ですが、以下の理由で実用上は問題になりません。

  • コンポーネント化: React、Vue、Svelteなどのフレームワークを使えば、繰り返し使用するUIはコンポーネントとして定義できます
  • エディタサポート: Tailwind CSS Intellisenseなどのエディタ拡張により、クラス名の補完や検索が容易になります
  • 読みやすさ: 慣れてくると、ユーティリティクラスの組み合わせからデザインを直接イメージできるようになります

疑問2: すべてのプロジェクトでTailwind CSSを使うべきですか?

新しく始めるプロジェクトすべてでTailwind CSSを採用すべきなのか判断に迷います。

解決手段

Tailwind CSSが特に有効なケース:

  • 新規プロジェクト: 既存のCSSがないため、導入の障壁が低い
  • プロトタイピング: デザインの試行錯誤が多い段階で、高速に開発できる
  • チーム開発: 統一されたデザインシステムにより、一貫性が保ちやすい
  • 長期運用プロジェクト: CSSが無秩序に増殖することを防げる

従来のCSSアプローチが適しているケース:

  • 既存の大規模CSSがある: 移行コストが高い
  • シンプルな静的サイト: ユーティリティクラスを使うほど複雑でない
  • 学習コスト: チーム全体がTailwind CSSに慣れる時間がない

疑問3: Tailwind CSSを学ぶ順序は?

公式ドキュメントのどのセクションから学べば効率的なのか迷います。

解決手段

推奨される学習順序:

  1. Core concepts(今ここ): Tailwind CSSの基本思想とユーティリティクラスの概念を理解
  2. Installation: プロジェクトへの導入方法
  3. 頻出するカテゴリ: Layout、Spacing、Typography、Colorsなど
  4. 状態とレスポンシブ: hover、focus、ブレークポイントなどの実践的な使い方
  5. カスタマイズ: プロジェクト固有のデザインシステムの構築

すべてを暗記する必要はなく、必要に応じて公式ドキュメントを参照しながら実践することが最も効率的です。

疑問4: Tailwind CSSのクラス名は覚える必要がありますか?

数百種類あるユーティリティクラスをすべて暗記するのは現実的ではないように感じます。

解決手段

暗記は不要です。以下の方法で効率的に使用できます。

  • エディタ拡張を利用: Tailwind CSS Intellisenseなどのツールを使えば、クラス名の候補が自動的に表示されます
  • よく使うクラスは自然に覚える: padding、margin、color、font-sizeなど、頻繁に使用するクラスは実践を通じて自然に覚えます
  • 公式ドキュメントを参照: わからないクラスは公式ドキュメントで検索すれば、すぐに見つかります
  • 命名規則を理解: text-{size}, bg-{color}, p-{size} のような規則性を理解すれば、推測できるようになります

よくある失敗

失敗1: npm run dev を実行せずにブラウザで確認

失敗内容

HTMLファイルにユーティリティクラスを追加しただけで、npm run dev を実行せずにブラウザで確認してしまいました。

誤った例

# HTMLファイルを編集
$ vim src/index.html

# npm run dev を実行せずに、直接ブラウザで開く
# → スタイルが適用されない

エラーメッセージ/結果

ブラウザでは、テキストが表示されるものの、Tailwind CSSのスタイルが一切適用されず、装飾のない素のHTMLが表示されました。背景色、角丸、影などがすべて反映されていません。

模範例

# HTMLファイルを編集
$ vim src/index.html

# Tailwind CSSをビルド(必須)
$ npm run dev

# ブラウザで確認
# → スタイルが正しく適用される

ポイント

Tailwind CSSは、HTMLファイルで使用されているクラスを検出して、必要なCSSを生成します。npm run dev を実行しないと、output.css が生成または更新されないため、スタイルが適用されません。watch モードで起動しておけば、HTMLを編集するたびに自動的にCSSが再ビルドされます。

失敗2: output.css を .gitignore に追加せずにコミット

失敗内容

自動生成される output.css.gitignore に追加せず、Gitにコミットしてしまいました。

誤った例

# .gitignore に output.css を追加していない状態

$ git add .
$ git commit -m "Add ChitChat card"

# output.css もコミットされてしまう
# → リポジトリが肥大化する

エラーメッセージ/結果

output.css は数千行に及ぶ大きなファイルで、HTMLを変更するたびに内容が変わります。これをGitで管理すると、差分が大きくなり、リポジトリのサイズが不必要に増大します。また、コンフリクトも発生しやすくなります。

模範例

# .gitignore に output.css を追加
$ echo "src/output.css" >> .gitignore

$ git add .
$ git commit -m "Add ChitChat card"

# output.css はコミットされない

ポイント

output.cssinput.css と HTMLファイルから自動生成されるため、Gitで管理する必要はありません。.gitignore に追加することで、不要なファイルがコミットされることを防ぎます。ソースファイル(input.cssindex.html)だけを管理すれば、誰でも npm run dev で同じ output.css を生成できます。

失敗3: CDN版を本番環境で使用

失敗内容

学習段階でCDN版のTailwind CSSを使用した経験から、本番環境でもCDN版を使い続けてしまいました。

誤った例

<!-- 本番環境でCDN版を使用(非推奨) -->
<script src="https://cdn.tailwindcss.com"></script>

エラーメッセージ/結果

CDN版は以下の問題があります。

  • ファイルサイズが大きい: すべてのユーティリティクラスが含まれるため、数MBのファイルをダウンロードする必要がある
  • パフォーマンスが低い: JavaScriptでCSSを生成するため、初期表示が遅くなる
  • カスタマイズができない: テーマのカスタマイズやプラグインの使用ができない

模範例

# 本番環境では、ビルド版を使用
$ npm install -D tailwindcss
$ npm run build

# 生成された output.css をHTMLから読み込む
<!-- 本番環境では、ビルド済みCSSを使用 -->
<link href="./output.css" rel="stylesheet">

ポイント

CDN版は、学習やプロトタイピングには便利ですが、本番環境では必ずビルド版を使用すべきです。ビルド版は、実際に使用しているクラスだけを含むため、ファイルサイズが大幅に小さくなり、パフォーマンスが向上します。

失敗4: ユーティリティクラスの順序を気にしすぎる

失敗内容

ユーティリティクラスの記述順序に一貫性を持たせようとして、時間を浪費してしまいました。

誤った例

<!-- 順序を揃えようとして悩む -->
<div class="flex items-center bg-white p-6 rounded-xl shadow-lg">
  <!-- これで良いのか? -->
</div>

<div class="bg-white flex items-center p-6 rounded-xl shadow-lg">
  <!-- それともこっち? -->
</div>

エラーメッセージ/結果

クラスの順序を揃えることに時間を使いすぎて、本質的な開発が進みませんでした。また、順序を統一しても、CSSの適用結果は変わらないため、実質的な意味がありませんでした。

模範例

<!-- 順序は気にせず、読みやすさを優先 -->
<div class="flex items-center gap-x-4 bg-white p-6 rounded-xl shadow-lg">
  <!-- レイアウト → 装飾 のように、ざっくりとしたグルーピングで十分 -->
</div>

ポイント

Tailwind CSSのクラスは、記述順序に関わらず、CSSの詳細度とソースコードの順序で適用されます。クラスの順序を厳密に揃える必要はなく、読みやすさを優先すれば十分です。もし統一したい場合は、Prettierなどのフォーマッターを使用すると、自動的に整形されます。

失敗5: すべてのスタイルをユーティリティクラスで書こうとする

失敗内容

Tailwind CSSを学んだ直後、すべてのスタイルをユーティリティクラスで書こうとして、複雑になりすぎました。

誤った例

<!-- 複雑なアニメーションもユーティリティクラスで書こうとする -->
<div class="animate-spin duration-1000 ease-in-out ...">
  <!-- 20個以上のクラスが並ぶ -->
</div>

エラーメッセージ/結果

非常に複雑なスタイルやアニメーションをユーティリティクラスだけで表現しようとすると、クラス名が長大になり、可読性が低下しました。また、同じパターンを複数箇所で繰り返すことになり、保守性も悪化しました。

模範例

<!-- 複雑なスタイルはカスタムCSSで定義 -->
<div class="custom-complex-animation">
  <!-- シンプル -->
</div>
/* input.css */
@layer components {
  .custom-complex-animation {
    animation: complex-spin 1s ease-in-out infinite;
    transform-origin: center;
    /* 複雑なスタイルはここに集約 */
  }
}

ポイント

Tailwind CSSは万能ではありません。複雑なスタイルや、プロジェクト固有の繰り返しパターンは、カスタムCSSで定義する方が適切です。公式ドキュメントでも、@layer components を使用してカスタムコンポーネントを定義する方法が紹介されています。ユーティリティクラスとカスタムCSSを適切に使い分けることが重要です。

記載内容の翻訳

Overview

Tailwind CSSでは、多くの単一目的のプレゼンテーショナルクラス(ユーティリティクラス)をマークアップ内で直接組み合わせてスタイリングを行います。

例えば、上記のUIでは以下を使用しています。

displayとpaddingユーティリティ(flexshrink-0p-6)で全体的なレイアウトを制御

max-widthとmarginユーティリティ(max-w-smmx-auto)でカードの幅を制限し、水平方向に中央揃え

background-color、border-radius、box-shadowユーティリティ(bg-whiterounded-xlshadow-lg)でカードの外観をスタイリング

widthとheightユーティリティ(size-12)でロゴ画像の幅と高さを設定

gapユーティリティ(gap-x-4)でロゴとテキストの間隔を調整

font-size、color、font-weightユーティリティ(text-xltext-blackfont-mediumなど)でカードのテキストをスタイリング

このスタイリング方法は、多くの従来のベストプラクティスと矛盾していますが、一度試してみると、非常に重要な利点にすぐ気づくでしょう。

主な利点

作業が速くなる: クラス名を考える時間、セレクタについての決定、HTMLとCSSファイル間の切り替えをする必要がなく、デザインが非常に速く完成します

変更がより安全になる: 要素にユーティリティクラスを追加または削除しても、その要素にのみ影響するため、同じCSSを使用している別のページで誤って何かを壊す心配がありません

古いプロジェクトの保守が簡単になる: 何かを変更するには、プロジェクト内でその要素を見つけてクラスを変更するだけで、6か月間触れていないカスタムCSSがどのように機能するかを思い出す必要がありません

コードがよりポータブルになる: 構造とスタイリングの両方が同じ場所にあるため、UI全体の塊を簡単にコピー&ペーストでき、異なるプロジェクト間でも可能です

CSSの増加が止まる: ユーティリティクラスは非常に再利用可能なため、プロジェクトに新しい機能を追加するたびにCSSが線形に増え続けることがありません

これらの利点は小規模プロジェクトでも大きな違いを生みますが、大規模で長期間運用されるプロジェクトに取り組むチームにとってはさらに価値があります。

Why not just use inline styles?

このアプローチに対する一般的な反応は、「これってインラインスタイルじゃないの?」という疑問です。ある意味ではその通りです。クラス名を割り当ててそのクラスをスタイリングするのではなく、要素に直接スタイルを適用しています。

しかし、ユーティリティクラスを使用することには、インラインスタイルに比べて多くの重要な利点があります。例えば:

制約のあるデザイン: インラインスタイルを使用すると、すべての値がマジックナンバーになります。ユーティリティを使用すると、事前定義されたデザインシステムからスタイルを選択するため、視覚的に一貫性のあるUIを構築することがはるかに簡単になります

hover、focus、その他の状態: インラインスタイルではhoverやfocusなどの状態をターゲットにできませんが、Tailwindの状態バリアントを使用すると、ユーティリティクラスでこれらの状態を簡単にスタイリングできます

メディアクエリ: インラインスタイルではメディアクエリを使用できませんが、Tailwindのレスポンシブバリアントを使用すると、完全にレスポンシブなインターフェイスを簡単に構築できます

公式ドキュメントには、hover と active スタイルを含む、完全にレスポンシブなコンポーネントの例が示されています。

今回のまとめ

お疲れさまでした。Tailwind CSSの「Styling with utility classes - Overview」と「Why not just use inline styles?」セクションを実際に手を動かして学習しました。

今回学習したことは以下の3点です。

  • Tailwind CSSのユーティリティクラスによるスタイリングアプローチ: HTMLに直接クラスを記述することで、CSSファイルを書かずにデザインを実装できる新しい開発手法を体験し、CSS フレームワークとしての基本的な考え方を理解しました
  • インラインスタイルとの3つの決定的な違い: デザインシステムによる一貫性、hover/focus状態の管理、レスポンシブデザインの実装という、インラインスタイルでは実現できない機能をnpm パッケージとwatch モード 自動ビルドを活用しながら実践しました
  • レスポンシブバリアントとhoverバリアントの仕組み: sm: プレフィックスが640px以上で適用されるメディアクエリであること、hover: プレフィックスが疑似クラスに相当することを、Chrome開発者ツールで実際に確認して理解しました

それでは、また次の記事でお会いしましょう。

  • LINE
  • -dev, TailwindCSS