ユーティリティファーストの考え方
この章では、Tailwind CSS の核心である「ユーティリティファースト」の考え方を理解します。
ユーティリティクラスとは
ユーティリティクラスは、単一の CSS プロパティを適用するクラスです。
<!-- 各クラスが 1 つのプロパティを担当 -->
<div class="flex items-center justify-between p-4 bg-white rounded-lg shadow-sm">
...
</div>
| クラス | 対応する CSS |
|---|---|
flex | display: flex |
items-center | align-items: center |
justify-between | justify-content: space-between |
p-4 | padding: 1rem |
bg-white | background-color: #fff |
rounded-lg | border-radius: 0.5rem |
shadow-sm | box-shadow: ... |
なお、v3 の shadow は v4 では shadow-sm に名称が変わっています (影のスケールが 1 段ズレています)。
従来の CSS との比較
従来のアプローチ
.card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
background-color: white;
border-radius: 0.5rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
<div class="card">...</div>
ユーティリティファースト
<div class="flex items-center justify-between p-4 bg-white rounded-lg shadow-sm">
...
</div>
なぜユーティリティファーストか
1. クラス名を考えなくてよい
従来の CSS では、適切なクラス名を考えるのに時間がかかります。
/* 何と名付ける? */
.card-wrapper { }
.card-container { }
.card-outer { }
.product-card-layout { }
ユーティリティクラスなら、直接スタイルを記述するだけです。
2. CSS が肥大化しない
従来のアプローチでは、プロジェクトが進むにつれ CSS が増え続けます。
/* 似たようなスタイルが増殖 */
.card { padding: 1rem; }
.card-large { padding: 1.5rem; }
.card-small { padding: 0.5rem; }
.product-card { padding: 1rem; }
.user-card { padding: 1rem; }
Tailwind CSS では、使用したクラスのみが出力されます。
3. 変更が安全
従来の CSS では、1 つのクラスを変更すると他の場所に影響する可能性があります。
/* この変更は安全? */
.card {
padding: 1rem; /* → 2rem に変更したら... */
}
ユーティリティクラスは各要素に閉じているため、影響範囲が明確です。
4. デザインシステムの強制
Tailwind CSS は事前定義された値を使用するため、一貫したデザインを維持できます。
<!-- 決められたスケールから選択 -->
<div class="p-1">4px</div>
<div class="p-2">8px</div>
<div class="p-4">16px</div>
<div class="p-8">32px</div>
<!-- 任意の値も可能だが、推奨されない -->
<div class="p-[17px]">17px</div>
任意の値 (p-[17px]) は便利ですが、デザインの一貫性が損なわれる原因になります。まずは Tailwind のスケール (p-4 = 16px, p-5 = 20px) で対応できないか検討しましょう。v4 では p-17 のように角括弧なしでもスケール上にない整数値を指定できますが、p-17 は 17 × 0.25rem = 4.25rem (17px ではない) となる点に注意してください。スケール外の値を多用するとデザインの一貫性が損なわれる点は同じです。
命名規則
Tailwind CSS のクラス名は直感的な規則に従っています。
パターン 1: プロパティ-値
<div class="text-center"> <!-- text-align: center -->
<div class="font-bold"> <!-- font-weight: bold -->
<div class="bg-blue-500"> <!-- background-color: ... -->
パターン 2: プロパティ-方向-値
<div class="p-4"> <!-- padding: 1rem (全方向) -->
<div class="px-4"> <!-- padding-left/right: 1rem -->
<div class="pt-4"> <!-- padding-top: 1rem -->
<div class="mt-4"> <!-- margin-top: 1rem -->
パターン 3: 条件-プロパティ-値
<div class="hover:bg-blue-600"> <!-- ホバー時 -->
<div class="md:flex"> <!-- 768px 以上 -->
<div class="dark:bg-gray-800"> <!-- ダークモード -->
スペーシングスケール
Tailwind CSS は 4px ベースのスケールを使用します。
| クラス | 値 |
|---|---|
0 | 0px |
1 | 4px (0.25rem) |
2 | 8px (0.5rem) |
3 | 12px (0.75rem) |
4 | 16px (1rem) |
6 | 24px (1.5rem) |
8 | 32px (2rem) |
12 | 48px (3rem) |
16 | 64px (4rem) |
HTML が長くなる問題
ユーティリティクラスを使うと、HTML が長くなることがあります。
<button class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
ボタン
</button>
解決策 1: コンポーネント化
function Button({ children }: { children: React.ReactNode }) {
return (
<button className="inline-flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
{children}
</button>
)
}
// 使用時
<Button>クリック</Button>
解決策 2: @apply ディレクティブ
/* 使いすぎに注意。必要な場合は使用可能 */
.btn-primary {
@apply inline-flex items-center justify-center px-4 py-2;
@apply text-sm font-medium text-white;
@apply bg-blue-600 hover:bg-blue-700;
@apply rounded-md shadow-sm;
}
@apply の多用は、ユーティリティファーストの利点を損なうため、コンポーネント化 (解決策 1) を優先してください。コンポーネントレベルの抽象化が必要な場合は、16 章 / カスタマイズ で紹介する @utility ディレクティブも検討してください。
v4 では @apply にファイルスコープの制約があります。メインの CSS ファイル以外 (CSS Modules や Vue/Svelte の <style> ブロック等) で使用する場合は、@reference ディレクティブでテーマ定義元のファイルを参照する必要があります。
/* 別ファイルで @apply を使う場合 */
@reference "../../styles/main.css";
.my-component {
@apply text-blue-500;
}
まとめ
- ユーティリティクラスは単一の CSS プロパティを適用
- クラス名を考えず、CSS の肥大化を防ぐ
- 変更が安全で、デザインの一貫性を維持
- 規則的な命名で学習しやすい
- 長いクラスはコンポーネント化で解決
次に読む
- Flexbox レイアウト — ユーティリティを組み合わせてレイアウトを組む
- カスタマイズ —
@theme@utilityで独自のユーティリティを定義 - Tailwind CSS ガイド 目次 — 全 18 章の構成に戻る