Tailwind CSS初心者が絶対ハマる落とし穴

2024/07/11に公開

ムーザルちゃんねるのzaruです。今回はムーさんと、Tailwind CSS初心者が絶対ハマる落とし穴について話しました。Tailwind CSSを使い始めた人、あるいはまだ使ったことがない人には是非見てほしいです。すでにこの落とし穴から抜け出している人はあるよねーって感じで眺めてください。

https://youtu.be/LMixhEfxI9k
すごいサムネイル…

ハマるポイント

  1. クラス名の動的指定
  2. クラス名のコンフリクト

クラス名の動的指定

例えば、通常は背景を青だけど、エラーの時は赤くしたい。そんなときにJavaScriptでクラス名を組み立てると以下のように書きがちです。bg--500 は固定なので変化する red blue だけ変数で組み立てるやり方です。

const color = error ? 'red' : 'blue';
<div class={`bg-${color}-500`}></div>

実はこれはスタイルは適用されません。

解決策としては以下のようにクラス名の文字列をすべて書かないといけません。

const color = error ? 'bg-red-500' : 'bg-blue-500';
<div class={color}></div>

なぜクラス名を動的にするとだめか

Tailwind CSSは、あらかじめ定義されているたくさんのスタイルから、必要なものだけを抽出するようになっています。


結果として、ミニマムなCSSファイルが手に入る

そして、必要なクラス名を抽出する仕組みは非常にシンプルです。HTMLやJSXなどの対象ファイルから、クラス名に一致する文字列があるかどうかで判定しています。つまり、文字列として完全一致でないとTailwind CSSは認識しません。


どのファイルを対象とするかは設定できる


クラス名が一致したら、スタイル定義を出力してくれる

また、クラス名はクラス属性に書く必要はなく、コメントや文中のテキストなんでも良いです。

<div>
  <!-- TODO: bg-red-500にしよう -->
  背景はbg-blue-500
</div>

これでも bg-red-500bg-blue-500 はスタイルが抽出されてCSSファイルが作成されます。つまり極端なことを言うと、この組み合わせであればクラス名を動的にしてもスタイルは適用されてしまいます。

// エラーはbg-red-500にして、通常はbg-blue-500にするぞ
const color = error ? 'red' : 'blue';
<div class={`bg-${color}-500`}></div>

しかしこれはコメントに依存していて、たまたまスタイルが適用されているだけなので危険です。

クラス名のコンフリクト

共通コンポーネントなどで、デフォルトのスタイルが適宜されており、それを利用する側がカスタマイズできるようにしている場合、デフォルトクラス名と、カスタマイズしたクラス名がコンフリクトすることがあります。

function Component({customClass}) {
  // デフォルトの背景は黄色
  return <div className={`bg-yellow-500 ${customClass}`}></div>
}

// 背景を赤くカスタマイズしたい
<Component customClass="bg-red-500" />

このコンポーネントに指定されるクラス属性は bg-yellow-500 bg-red-500 という文字列になります。このように背景色を指定するものが同時に指定されると、どのスタイルが適用されるかは場合によって異なり不安定な挙動になります。

このケースで言えば、あとから指定した bg-red-500 は無視され、デフォルトの bg-yellow-500 が適用されます。これは、Tailwind CSSが出力するCSSファイルのスタイル定義が、クラス名のアルファベット順になっているからです。redよりもyellowの方がファイルの下に定義され、結果としてCSSのあと勝ちになります。

解決策はシンプルに tailwind-merge というライブラリを使うことです。

import { twMerge } from 'https://cdn.jsdelivr.net/npm/tailwind-merge@2.4.0/+esm';
function Component({customClass}) {
  // twMergeでよしなにやってもらう
  return <div className={twMerge('bg-yellow-500', customClass)}></div>
}

<Component customClass="bg-red-500" />

おわりに

Tailwind CSSは慣れれば効率的にデザインができますが、他のCSSフレームワークやツールと比較すると方言があったりとクセがあります。しかし、Tailwind CSS周辺のライブラリやツールも充実してきているので、僕は好きです。賛否両論あるTailwind CSSですが、穴に気をつけつつ是非使ってみてください。

Tailwind Variantsも気になるな…?
https://www.tailwind-variants.org/

ムーザルちゃんねる

Discussion