第3章 Tailwind CSS の設計思想
第1章で歴史を、第2章で誕生の経緯を見てきました。この章では、Tailwind の根っこにある Utility First(ユーティリティファースト) という思想を、メリットだけでなく、それに向けられる批判への反論まで含めて、じっくり理解します。ここを腰を据えて理解しておくと、第4部以降で個々のクラスを学ぶときの「なぜこう書くのか」がすべてつながります。
3.1 Utility First とは何か
Utility First とは、単一の役割だけを持つ小さなクラス(ユーティリティクラス)を組み合わせて、デザインを組み立てるという考え方です。「まずユーティリティで作る」から Utility First です。
具体例を見ましょう。よくある「カード」の UI を、従来の方法と Tailwind で書き比べます。
従来の方法(BEM 風):
<div class="card">
<h2 class="card__title">通知</h2>
<p class="card__body">新しいメッセージがあります。</p>
</div>
.card {
max-width: 24rem;
padding: 1.5rem;
background-color: white;
border-radius: 0.5rem;
box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);
}
.card__title {
font-size: 1.25rem;
font-weight: 700;
}
.card__body {
color: #4b5563;
}
Tailwind の方法:
<div class="max-w-sm p-6 bg-white rounded-lg shadow">
<h2 class="text-xl font-bold">通知</h2>
<p class="text-gray-600">新しいメッセージがあります。</p>
</div>
Tailwind 版では、CSS ファイルを 1 行も書いていません。max-w-sm(最大幅)、p-6(内側の余白)、bg-white(背景白)、rounded-lg(角丸)、shadow(影)といったユーティリティクラスを HTML 側で組み合わせるだけで、同じ見た目を作っています。
このとき生成される CSS は、おおよそ次のような単機能のルールの集まりです(実際の出力は簡略化しています)。
.p-6 { padding: 1.5rem; }
.bg-white { background-color: #fff; }
.rounded-lg { border-radius: 0.5rem; }
/* ... 使ったクラスの分だけ ... */
ポイントは、これらのクラスはこのカード専用ではないことです。p-6 も bg-white も、サイト中のどこでも何度でも使い回せます。だから、新しい部品を作っても CSS は増えません。
3.2 なぜインラインスタイルではダメなのか
ここで多くの人が抱く疑問があります。「クラスをたくさん並べるくらいなら、style 属性で直接書くインラインスタイルと同じでは?」というものです。
<!-- インラインスタイル -->
<div style="padding: 1.5rem; background-color: white; border-radius: 0.5rem;">...</div>
見た目だけなら、確かに似ています。しかし Tailwind のユーティリティには、インラインスタイルにはできないことが 3 つあります。これが決定的な差です。
(1) 制約(デザインの一貫性)
インラインスタイルでは padding: 13px でも padding: 17px でも何でも書けてしまいます。自由すぎて、気づけば余白がバラバラになります。一方 Tailwind の p-4・p-6・p-8 は、あらかじめ決められたスケール(4px 刻みなど)の上に乗っています。選べる値が制限されているからこそ、誰が書いても余白や色が揃い、デザインに一貫性が生まれます。これは「制約は不自由ではなく、品質を守る仕組み」という Tailwind の重要な思想です(3.3 で詳述)。
(2) 状態(ホバー・フォーカスなど)
インラインスタイルでは、:hover や :focus のような状態に応じたスタイルが書けません。マウスを乗せたら色を変える、といったことが style 属性では不可能です。Tailwind なら hover:bg-blue-700 のように、バリアントを付けるだけで状態に対応できます。
<button class="bg-blue-500 hover:bg-blue-700">送信</button>
(3) レスポンシブ(画面幅への対応)
インラインスタイルではメディアクエリ(画面幅に応じた切り替え)が書けません。Tailwind なら md: のようなバリアントで対応できます。
<div class="text-sm md:text-lg">画面が広いと大きい文字</div>
この (2)(3) ができることこそ、「Tailwind はインラインスタイルとは違う」と言える根拠です。公式ドキュメントも、ユーティリティクラスを使う理由として、まさにこの「制約・状態・レスポンシブ」を挙げています。
3.3 「制約のあるデザイン」がもたらす一貫性
3.2 で触れた「制約」を、もう少し深く見ます。これは Tailwind を理解するうえで最も大切な発想の 1 つです。
たとえば文字色を考えてみましょう。CSS では color に約 1,600 万色を指定できます。自由です。しかしチーム開発では、この自由がバラつきを生みます。ある人は #3b82f6、別の人は #3c83f5、また別の人は #3a80f0——ほとんど同じだけれど微妙に違う青が、サイト中に散らばっていきます。
Tailwind は、色を blue-500・blue-600 のような決められたパレットとして提供します。選択肢を絞ることで、「誰が書いても同じ青になる」状態を作ります。余白も --spacing を基準にした段階的な値(p-4・p-6・p-8…)として扱い、フォントサイズも sm/base/lg/xl…と段階が決まっています。
これは デザイントークン(デザイン上の決め事を、値の一覧として定義したもの)の考え方そのものです。Tailwind を使うということは、暗黙のうちに「制約のあるデザインシステムの上で作業する」ことを意味します。だからこそ、デザイナーがいなくても、ある程度整った見た目になりやすいのです。この制約は第5章「テーマシステム」で自分好みにカスタマイズできます。
3.4 関心の分離の再定義 — 分けるべきは HTML と CSS ではない
第2章で見た Adam Wathan の主張を、ここで改めて整理します。彼の主張はこうです。
本当に分けるべきなのは「HTML と CSS」ではなく、「再利用できないもの」と「再利用できるもの」だ。
従来の .card__title のようなクラスは、「カードのタイトル」という特定の文脈に縛られていて再利用できません。ファイルは分かれていても、HTML の都合に CSS が縛られています。
Tailwind のユーティリティは逆です。text-xl も font-bold も、特定の文脈に縛られておらず、どこでも再利用できます。HTML 側は「このユーティリティたちを使う」と宣言するだけ。依存の向きが「CSS → HTML」から「HTML → CSS」へ反転しています。
この反転によって、CSS は「特定のページのための、消すのが怖いコード」ではなく、「どこでも使える、安定した部品の集まり」になります。これが Tailwind の言う「関心の分離の再定義」です。
3.5 命名からの解放
第1章で、BEM の大きな負担は「命名」だと述べました。Tailwind は、この負担をほぼゼロにします。
p-6 bg-white rounded-lg shadow と書くとき、あなたは何も命名していません。「このカードを何と呼ぶか」「このタイトルのクラス名は何か」を考える必要がないのです。プログラミングで最も難しいことの 1 つが命名だとすれば、その難所を 1 つ丸ごと回避できるのは、地味ですが非常に大きな利点です。
もちろん、繰り返し使う部品は最終的にコンポーネント化します(第6部)。しかし「とりあえず作る」段階で命名を強制されないことは、開発のリズムを大きく軽くします。
3.6 CSS が線形に増えない理由
従来の方法では、ページや部品を追加するたびに CSS が増えました。新しいボタンを作れば新しいクラスと新しいルールが必要で、プロジェクトが大きくなるほど CSS ファイルは際限なく膨らみます。
Tailwind では、CSS の量は「使っているユーティリティの種類数」でほぼ頭打ちになります。p-4 を 1 か所で使おうと 1,000 か所で使おうと、生成される CSS は .p-4 { padding: 1rem; } の 1 つだけだからです。新しいページを 100 個追加しても、すでに使っているユーティリティの組み合わせで作る限り、CSS はほとんど増えません。
公式ドキュメントはこれを「CSS が線形に増えない(your CSS stops growing)」と表現しています。大規模で長期間運用されるプロジェクトほど、この性質は効いてきます。
3.7 「醜い HTML」問題への作者の回答
Tailwind に最もよく向けられる批判が、「クラスが大量に並んで HTML が読みにくい(醜い)」というものです。
<button class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
送信
</button>
確かに、初めて見ると面食らうでしょう。これに対する作者やコミュニティの回答は、おおむね次のとおりです。
- トレードオフである: HTML が「にぎやか」になる代わりに、CSS ファイルの肥大化・命名・詳細度の戦いといった、より深刻な問題から解放される。どちらの「醜さ」を引き受けるか、という選択である。
- 繰り返しはコンポーネント化で解決する: 同じボタンを何度も書くなら、Rails の部分テンプレートや React のコンポーネントとして 1 か所にまとめればよい。そうすれば、長いクラス列が見えるのは定義の 1 か所だけになる(第6部で詳しく扱います)。
- 見る場所が変わっただけ: 従来は「HTML を見て → CSS ファイルを開いて確認する」必要があった。Tailwind では、要素の見た目はその場の
classにすべて書いてある。ファイルを行き来せずに済むという利点の裏返しでもある。
「醜い HTML」は事実として認めつつ、それを上回る利益があり、かつコンポーネント化で実用上は緩和できる——これが Tailwind 側の立場です。この論争は重要なので、第28章「Tailwind CSS への批判と評価」で、批判側の主張も含めて改めて公平に扱います。
3.8 Utility First が向く場面・向かない場面の見取り図
最後に、思想を現実に当てはめるための見取り図を示します。Utility First は万能ではありません。
向いている場面:
- アプリケーションの UI(管理画面、ダッシュボード、SaaS など)。独自のデザインを、部品を組み合わせて素早く作りたいケース。
- コンポーネント志向のフレームワーク(React・Vue や、Rails の ViewComponent など)を使っていて、繰り返しをコンポーネントに畳み込めるケース。
- チームで開発し、デザインの一貫性を仕組みで担保したいケース。
向いていない・慎重になるべき場面:
- ごく小さな静的ページ 1 枚だけ。導入の手間が利益を上回ることがある。
- CMS が吐き出す本文 HTML のように、クラスを付けられない外部由来のマークアップを整えたいケース(ただしこれは
@tailwindcss/typographyのproseで対応できます。第11章)。 - コンポーネント化の仕組みがなく、同じ長いクラス列を手で何度もコピーするしかない環境。重複が負債になりやすい。
重要なのは、「向くか向かないか」はプロジェクトの性質とチームの体制で決まるということです。第31章「Tailwind CSS を選ぶべきか」で、この判断を具体的なチェックリストに落とし込みます。
ここまでで、Tailwind が「なぜそういう道具なのか」という土台が固まりました。次の第2部では、いよいよ Tailwind が内部でどう動いているのか——魔法に見える仕組みの正体に踏み込んでいきます。