Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第27章 Tailwind CSS のアンチパターン

この章は「禁止集」ではありません。挙げる項目は、どれも「絶対に使うな」というものではなく、「なぜ問題になりやすいか、いつなら許容できるか、どう判断するか」を示すものです。アンチパターンの多くは、道具自体が悪いのではなく、使いどころを誤ったときに痛むものです。判断基準として読んでください。

27.1 任意の値([...])の乱用

何が起きるか: p-[13px]・text-[#1a1a1a]・w-[327px] のような任意の値(第4章)が画面中に散らばると、第3章で得た「スケールという制約」が崩れ、デザインの一貫性が失われます。

なぜ問題か: 任意の値が多い場合、チームの採用スケールに沿っているかを見直す必要があります。数値が生成できるかとは別の判断です。1 つ 2 つなら問題ありませんが、増えてくると「テーマが整っていない」「デザインがスケールに沿っていない」という、より根本的な問題の兆候です。

判断基準: 「この値は本当に唯一無二か?」と問います。p-4 や p-5 で代用できないか。何度も使う値なら、[...] で散らすのではなく、テーマ変数として名前を付ける(第5章)。単発・例外的なら可、繰り返すならテーマへ、が基準です。

27.2 @apply でユーティリティを CSS に逃がしすぎる

何が起きるか: HTML をきれいに見せたいあまり、@apply で何でも CSS クラスにまとめてしまう(第22章)。

なぜ問題か: 独自クラスが増えるほど命名や CSS の管理が必要になり、見た目を調べるためのファイル移動も増えます。構造の重複まで解決できるかは別なので、何を共通化するかを第22章の基準で判断します。

判断基準: 構造や振る舞いも重複するなら、まずコンポーネント抽出を検討します。見た目だけを共有する小さな部品なら、@layer components のカスタムクラスも選択肢です。@apply の使用自体ではなく、命名や変更箇所が無用に増えていないかで判断します。

27.3 クラス名の動的文字列結合で検出漏れ

何が起きるか: text-${color}-600 のようにクラス名を動的に組み立てると、その式から必要な CSS を検出できません。

なぜ問題か: 第4章で見たとおり、Tailwind はソースをただのテキストとして走査し、完全なクラス名の文字列だけを拾います。text-${color}-600 は 1 つの文字列として認識されず、CSS が生成されません。補間式だけからは生成できません。ただし、別ファイルに完全なクラス名があったり、watch 中に既出ルールが残っていたりすると、偶然動く場合があります。クリーンビルドでも確認し、別の箇所の記述に依存させないようにします。

判断基準: クラス名はつねに完全な文字列で書く。プロパティで切り替えるなら、完全なクラス名のマッピングを用意する(第25章)。

// NG
<div className={`text-${color}-600`} />
// OK
const C = { red: 'text-red-600', blue: 'text-blue-600' }
<div className={C[color]} />

これは判断の余地が小さい、ほぼ絶対のルールです。

27.4 「巨大コンポーネント 1 個」化(抽出粒度の誤り)

何が起きるか: 重複を嫌うあまり、何でも 1 つの巨大なコンポーネントに詰め込み、無数の props で分岐させる。

なぜ問題か: コンポーネント化は良いことですが、粒度を誤ると逆効果です。1 つの <Card> が 30 個の props を持ち、内部が条件分岐だらけになると、もはや誰も理解・修正できません。これは「重複を避ける」ことに囚われすぎた結果です。

判断基準: 「少しの重複は、誤った抽象化よりマシ」という原則を思い出します。無理に共通化せず、似て非なるものは別コンポーネントに分ける勇気を持つ。バリアントは CVA(第23章)で整理できる範囲に留める、が基準です。

27.5 デザイントークンを無視した直値の散乱

何が起きるか: text-[#1a1a1a]・bg-[#fafafa] のような直値の色・サイズが、テーマを無視して散らばる。

なぜ問題か: 27.1 の色版です。直値で書くと、ブランド変更やダークモード対応(第18章)のときに全置換が必要になり、保守不能に近づきます。

判断基準: 色・余白・フォントなど、デザインの基幹となる値はデザイントークンに集約する(第5章・第26章)。とくに色は、ダークモードのことを考えると直値を避けるべき筆頭です。

27.6 既存 CSS との二重管理

何が起きるか: Tailwind を導入したのに、従来の CSS ファイルも併存し、同じ要素が両方で別々にスタイリングされる。

なぜ問題か: 「この余白は Tailwind のクラス? それとも CSS ファイル?」と、見るべき場所が 2 つになります。第1章で見た「どこで効いているか分からない」状態に逆戻りします。

判断基準: 段階的移行(第24章)は問題ありませんが、「この画面は Tailwind に寄せる」と単位を決めて移行し、中途半端な二重管理を長期間放置しない。新規分は Tailwind、と方針を統一する、が基準です。

27.7 アンチパターンの矯正手順

すでにこれらのアンチパターンに陥っている場合の、現実的な直し方です。

  1. 検出漏れ(27.3)から直す: スタイルが当たっていないバグなので最優先。動的クラス名を完全な文字列に置き換える。
  2. 直値・任意値をテーマに寄せる(27.1, 27.5): 繰り返し使われている直値を洗い出し、デザイントークンに昇格させる。
  3. 重複をコンポーネント化(27.2, 27.4): 痛い箇所から段階的に抽出する。一度に全部やろうとしない。

完璧を目指さず、痛いところから順に直すのが、挫折しないコツです。

27.8 AI 生成 Tailwind のよくある崩れ方

AI の出力も、人が書いたコードと同じ基準で検査します。以下は特定モデルの傾向を断定するものではなく、出力をレビューするときの確認項目です。入力する規約は第26章、依頼例は付録Eを参照してください。

  • 任意の値の乱用(27.1): [327px] などの値が、チームで採用した寸法規約に沿っているか。
  • プロジェクトのトークンとの不一致: bg-blue-500・p-4 も標準のテーマトークン由来です。ただし、採用済みの bg-primary や余白規約を無視して選んでいないかを確認します。これは bg-[#123456] のような CSS の直値とは別の問題です。
  • 動的クラス名(27.3): props から bg-${color} を組み立てていないか。
  • レスポンシブ・アクセシビリティの欠落: 見た目は整っていても、sm:/md: の設計や aria-*・フォーカス可視化(第21章)が抜けていないか。

レビュー観点としては、(1) クラスが実在するか、(2) レスポンシブが破綻していないか、(3) アクセシビリティを落としていないか、(4) 色・余白・角丸・影がトークンに沿っているか、(5) text-${color} のような検出漏れがないか、をチェックします。AI の出力は「下書き」として受け取り、本章の基準で整える——これが AI 時代の実務作法です。

参考資料