1. コアコンセプト
  2. ユーティリティクラスによるスタイリング

コアコンセプト

ユーティリティクラスによるスタイリング

プリミティブなユーティリティの制約されたセットから複雑なコンポーネントを構築する。

概要

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

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="/img/logo.svg" 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>

たとえば、上記の UI では以下を使用しました。

  • レイアウト全体を制御するためのdisplayおよびpaddingユーティリティ (flexshrink-0、およびp-6)
  • カードの幅を制限し、水平方向に中央揃えにするためのmax-widthおよびmarginユーティリティ (max-w-smおよびmx-auto)
  • カードの外観をスタイル設定するためのbackground-colorborder-radius、およびbox-shadowユーティリティ (bg-whiterounded-xl、およびshadow-lg)
  • ロゴ画像の幅と高さを設定するためのwidthおよびheightユーティリティ (size-12)
  • ロゴとテキストの間隔を処理するためのgapユーティリティ (gap-x-4)
  • カードテキストをスタイル設定するためのfont-sizecolor、およびfont-weightユーティリティ (text-xltext-blackfont-mediumなど)

この方法でスタイルを設定することは、従来のベストプラクティスに多く反していますが、一度試してみると、非常に重要な利点にすぐに気付くでしょう。

  • より速く作業を完了できる — クラス名を考えたり、セレクターについて決定したり、HTMLファイルとCSSファイルを切り替えたりする時間を費やす必要がないため、デザインが非常に速くまとまります。
  • 変更がより安全に感じられる — ユーティリティクラスを要素に追加または削除しても、その要素にのみ影響するため、同じCSSを使用している別のページを誤って壊してしまう心配はありません。
  • 古いプロジェクトのメンテナンスが容易になる — 何かを変更するということは、プロジェクト内でその要素を見つけてクラスを変更するだけであり、6か月間触れていないカスタムCSSがどのように機能するかを思い出そうとする必要はありません。
  • コードの移植性が向上する — 構造とスタイルが同じ場所に存在するため、UIのチャンク全体を異なるプロジェクト間でも簡単にコピーアンドペーストできます。
  • CSSの肥大化が止まる — ユーティリティクラスは非常に再利用可能であるため、CSSはプロジェクトに追加するすべての新機能とともに線形に増え続けることはありません。

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

なぜインラインスタイルを使用しないのですか?

このアプローチに対する一般的な反応は、「これは単なるインラインスタイルではないか?」と疑問に思うことですが、ある意味ではそうです。クラス名を割り当ててそのクラスをスタイル設定する代わりに、要素に直接スタイルを適用しています。

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

  • 制約のある設計 — インラインスタイルを使用すると、すべての値がマジックナンバーになります。ユーティリティを使用すると、事前定義されたデザインシステムからスタイルを選択するため、視覚的に一貫性のあるUIをはるかに簡単に構築できます。
  • ホバー、フォーカス、その他の状態 — インラインスタイルはホバーやフォーカスなどの状態をターゲットにすることはできませんが、Tailwind の状態バリアントを使用すると、ユーティリティクラスでこれらの状態を簡単にスタイル設定できます。
  • メディアクエリ — インラインスタイルではメディアクエリを使用できませんが、Tailwind のレスポンシブバリアントを使用すると、完全にレスポンシブなインターフェイスを簡単に構築できます。

このコンポーネントは完全にレスポンシブであり、ホバーおよびアクティブスタイルを持つボタンが含まれており、完全にユーティリティクラスで構築されています。

Woman's Face

エリン・リンドフォード

プロダクトエンジニア

<div class="flex flex-col gap-2 p-8 sm:flex-row sm:items-center sm:gap-6 sm:py-4 ...">
<img class="mx-auto block h-24 rounded-full sm:mx-0 sm:shrink-0" src="/img/erin-lindford.jpg" 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="border-purple-200 text-purple-600 hover:border-transparent hover:bg-purple-600 hover:text-white active:bg-purple-700 ...">
Message
</button>
</div>
</div>

ユーティリティクラスで考える

ホバー状態とフォーカス状態のスタイル設定

ホバーやフォーカスなどの状態の要素をスタイル設定するには、ターゲットにする状態をユーティリティにプレフィックスとして追加します。たとえば、hover:bg-sky-700などです。

このボタンにカーソルを合わせると、背景色が変化するのがわかります。

<button class="bg-sky-500 hover:bg-sky-700 ...">Save changes</button>

これらのプレフィックスは、Tailwind ではバリアントと呼ばれ、そのバリアントの条件が一致する場合にのみ、ユーティリティクラスのスタイルを適用します。

hover:bg-sky-700クラスに対して生成されたCSSは次のようになります。

生成されたCSS
.hover\:bg-sky-700 {
&:hover {
background-color: var(--color-sky-700);
}
}

このクラスは、要素がホバーされない限り何も実行しないことに注意してください。その唯一の仕事は、ホバースタイルを提供することであり、それ以外には何もありません。

これは、従来のCSSの書き方とは異なります。従来のCSSでは、単一のクラスが通常、多くの状態のスタイルを提供します。

HTML
<button class="btn">Save changes</button>
<style>
.btn {
background-color: var(--color-sky-500);
&:hover {
background-color: var(--color-sky-700);
}
}
</style>

Tailwind では、hover:disabled:を組み合わせるなど、複数の条件が一致した場合にユーティリティを適用するためにバリアントを積み重ねることもできます。

<button class="bg-sky-500 disabled:hover:bg-sky-500 ...">Save changes</button>

詳細については、ホバー、フォーカス、その他の状態の要素のスタイル設定に関するドキュメントをご覧ください。

メディアクエリとブレークポイント

ホバー状態やフォーカス状態と同様に、スタイルを適用するブレークポイントをユーティリティにプレフィックスとして追加することで、異なるブレークポイントで要素をスタイル設定できます。

この例のサイズを変更して、レイアウトの変化を確認してください。

01
02
03
04
05
06
<div class="grid grid-cols-2 sm:grid-cols-3">
<!-- ... -->
</div>

上記の例では、sm:プレフィックスは、grid-cols-3smブレークポイント以上でのみトリガーされるようにします。これは、デフォルトで40remです。

生成されたCSS
.sm\:grid-cols-3 {
@media (width >= 40rem) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}

詳細については、レスポンシブデザインのドキュメントをご覧ください。

ダークモードのターゲット設定

ダークモードで要素をスタイル設定するには、ダークモードがアクティブなときに適用するユーティリティにdark:プレフィックスを追加するだけです。

ライトモード

逆さまに書く

ゼログラビティペンは、逆さまを含め、あらゆる向きで書くことができます。宇宙空間でも機能します。

ダークモード

逆さまに書く

ゼログラビティペンは、逆さまを含め、あらゆる向きで書くことができます。宇宙空間でも機能します。

<div class="bg-white dark:bg-gray-800 rounded-lg px-6 py-8 ring shadow-xl ring-gray-900/5">
<div>
<span class="inline-flex items-center justify-center rounded-md bg-indigo-500 p-2 shadow-lg">
<svg
class="h-6 w-6 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<!-- ... -->
</svg>
</span>
</div>
<h3 class="text-gray-900 dark:text-white mt-5 text-base font-medium tracking-tight ">Writes upside-down</h3>
<p class="text-gray-500 dark:text-gray-400 mt-2 text-sm ">
The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
</p>
</div>

ホバー状態やメディアクエリと同様に、理解しておくべき重要なことは、単一のユーティリティクラスには、ライトスタイルとダークスタイルの両方が決して含まれないということです。ダークモードでスタイルを設定するには、複数のクラスを使用します。1つはライトモードスタイル用、もう1つはダークモードスタイル用です。

生成されたCSS
.dark\:bg-gray-800 {
@media (prefers-color-scheme: dark) {
background-color: var(--color-gray-800);
}
}

詳細については、ダークモードのドキュメントをご覧ください。

クラス構成の使用

Tailwind では、多くの場合、複数のクラスを使用して、単一のCSSプロパティの値を構築します。たとえば、複数のフィルターを要素に追加するなどです。

HTML
<div class="blur-sm grayscale">
<!-- ... -->
</div>

これらのエフェクトはどちらもCSSのfilterプロパティに依存しているため、Tailwind はCSS変数を使用して、これらのエフェクトを一緒に構成できるようにしています。

生成されたCSS
.blur-sm {
--tw-blur: blur(var(--blur-sm));
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-grayscale,);
}
.grayscale {
--tw-grayscale: grayscale(100%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-grayscale,);
}

上記の生成されたCSSはわずかに簡略化されていますが、ここでの秘訣は、各ユーティリティが、適用することを意図したエフェクトのためだけにCSS変数を設定することです。次に、filterプロパティはこれらの変数をすべて調べ、変数が設定されていない場合は何もしません。

Tailwind は、グラデーションシャドウカラートランスフォームなどにも同じアプローチを使用しています。

任意の値の使用

Tailwind の多くのユーティリティは、bg-blue-500text-xlshadow-mdなどのテーマ変数によって駆動されます。これらは、基盤となるカラーパレット、タイプスケール、およびシャドウにマッピングされます。

テーマ外の1回限りの値を使用する必要がある場合は、任意の値を指定するための特別な角かっこ構文を使用します。

HTML
<button class="bg-[#316ff6] ...">
Sign in with Facebook
</button>

これは、カラーパレット外の1回限りの色 (上記の Facebook ブルーなど) に役立ちますが、非常に具体的なグリッドのような複雑なカスタム値が必要な場合にも役立ちます。

HTML
<div class="grid grid-cols-[24rem_2.5rem_minmax(0,1fr)]">
<!-- ... -->
</div>

テーマ値を使用している場合でも、calc()などのCSS機能を使用する必要がある場合にも役立ちます。

HTML
<div class="max-h-[calc(100dvh-(--spacing(6))]">
<!-- ... -->
</div>

任意のプロパティ名を含む完全に任意のCSSを生成するための構文もあり、CSS変数を設定するのに役立ちます。

HTML
<div class="[--gutter-width:1rem] lg:[--gutter-width:2rem]">
<!-- ... -->
</div>

詳細については、任意の値の使用に関するドキュメントをご覧ください。

これはどのように機能するのですか?

Tailwind CSS は、他のCSSフレームワークで使用されている可能性のある大きな静的スタイルシートではありません。CSSをコンパイルするときに実際に使用しているクラスに基づいて、必要なCSSを生成します。

これは、プロジェクト内のすべてのファイルをスキャンして、クラス名である可能性のあるシンボルを探すことによって行われます。

Button.jsx
export default function Button({ size, children }) {
let sizeClasses = {
md: "px-4 py-2 rounded-md text-base",
lg: "px-5 py-3 rounded-lg text-lg",
}[size];
return (
<button type="button" className={`font-bold ${sizeClasses}`}>
{children}
</button>
);
}

Tailwind は、潜在的なクラスをすべて見つけた後、各クラスのCSSを生成し、実際に必要なスタイルのみを含む1つのスタイルシートにコンパイルします。

CSS はクラス名に基づいて生成されるため、Tailwind はbg-[#316ff6]のような任意の値を使用するクラスを認識し、値がテーマの一部でなくても、必要なCSSを生成できます。

この仕組みの詳細については、ソースファイル内のクラスの検出をご覧ください。

複雑なセレクター

要素を、ダークモード、特定のブレークポイント、ホバー時、および要素に特定のデータ属性がある場合など、条件の組み合わせでスタイル設定する必要がある場合があります。

Tailwind でそれがどのように見えるかの例を次に示します。

HTML
<button class="dark:lg:data-current:hover:bg-indigo-600 ...">
<!-- ... -->
</button>
簡略化されたCSS
@media (prefers-color-scheme: dark) and (width >= 64rem) {
button[data-current]:hover {
background-color: var(--color-indigo-600);
}
}

Tailwind は、group-hoverのようなものもサポートしており、特定の親がホバーされたときに要素をスタイル設定できます。

HTML
<a href="#" class="group rounded-lg p-8">
<!-- ... -->
<span class="group-hover:underline">Read more…</span>
</a>
簡略化されたCSS
@media (hover: hover) {
a:hover span {
text-decoration-line: underline;
}
}

このgroup-*構文は、group-focusgroup-active、およびその他多数のような他のバリアントでも機能します。

本当に複雑なシナリオ (特に制御できないHTMLをスタイル設定する場合) の場合、Tailwind は任意のバリアントをサポートしており、クラス名に直接必要なセレクターを記述できます。

HTML
<div class="[&>[data-active]+span]:text-blue-600 ...">
<span data-active><!-- ... --></span>
<span>This text will be blue</span>
</div>
簡略化されたCSS
div > [data-active] + span {
color: var(--color-blue-600);
}

インラインスタイルをいつ使用するか

インラインスタイルは、特に値がデータベースやAPIなどの動的なソースから来ている場合に、Tailwind CSS プロジェクトで依然として非常に役立ちます。

branded-button.jsx
export function BrandedButton({ buttonColor, textColor, children }) {
return (
<button
style={{
backgroundColor: buttonColor,
color: textColor,
}}
className="rounded-md px-3 py-1.5 font-medium"
>
{children}
</button>
);
}

クラス名としてフォーマットすると読みにくい非常に複雑な任意の値をインラインスタイルで使用することもできます。

HTML
<div class="grid-[2fr_max(0,var(--gutter-width))_calc(var(--gutter-width)+10px)]">
<div style="grid-template-columns: 2fr max(0, var(--gutter-width)) calc(var(--gutter-width) + 10px)">
<!-- ... -->
</div>

もう1つの便利なパターンは、インラインスタイルを使用して動的なソースに基づいてCSS変数を設定し、ユーティリティクラスでそれらの変数を参照することです。

branded-button.jsx
export function BrandedButton({ buttonColor, buttonColorHover, textColor, children }) {
return (
<button
style={{
"--bg-color": buttonColor,
"--bg-color-hover": buttonColorHover,
"--text-color": textColor,
}}
className="bg-(--bg-color) text-(--text-color) hover:bg-(--bg-color-hover) ..."
>
{children}
</button>
);
}

重複の管理

ユーティリティクラスだけでプロジェクト全体を構築すると、必然的に特定のパターンを繰り返して、異なる場所で同じデザインを再現することになります。

たとえば、ここでは、各アバター画像のユーティリティクラスが5回繰り返されています。

コントリビューター

204
<div>
<div class="flex items-center space-x-2 text-base">
<h4 class="font-semibold text-slate-900">Contributors</h4>
<span class="bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700 ...">204</span>
</div>
<div class="mt-3 flex -space-x-2 overflow-hidden">
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt="" />
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
</div>
<div class="mt-3 text-sm font-medium">
<a href="#" class="text-blue-500">+ 198 others</a>
</div>
</div>

パニックにならないでください!実際には、これは心配しているような問題ではなく、それに対処するための戦略は、すでに日常的に行っていることです。

ループの使用

レンダリングされたページに複数回表示されるデザイン要素の多くは、実際のマークアップがループでレンダリングされるため、実際には1回しか作成されていません。

たとえば、このガイドの冒頭にある重複するアバターは、実際のプロジェクトではほぼ確実にループでレンダリングされます。

コントリビューター

204
<div>
<div class="flex items-center space-x-2 text-base">
<h4 class="font-semibold text-slate-900">Contributors</h4>
<span class="bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700 ...">204</span>
</div>
<div class="mt-3 flex -space-x-2 overflow-hidden">
{#each contributors as user}
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src={user.avatarUrl} alt={user.handle} />
{/each}
</div>
<div class="mt-3 text-sm font-medium">
<a href="#" class="text-blue-500">+ 198 others</a>
</div>
</div>

要素がこのようにループでレンダリングされる場合、実際のクラスリストは1回だけ記述されるため、解決すべき実際の重複問題はありません。

マルチカーソル編集の使用

重複が単一ファイル内の要素のグループにローカライズされている場合、それに対処する最も簡単な方法は、マルチカーソル編集を使用して、各要素のクラスリストをすばやく選択して同時に編集することです。

これが最終的に最良のソリューションになることがどれほど多いかに驚かれることでしょう。重複するクラスリストすべてをすばやく同時に編集できる場合は、追加の抽象化を導入するメリットはありません。

<nav class="flex justify-center space-x-4">  <a href="/dashboard" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900">    Home  </a>  <a href="/team" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900">    Team  </a>  <a href="/projects" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900">    Projects  </a>  <a href="/reports" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900">    Reports  </a></nav>

コンポーネントの使用

複数のファイルで一部のスタイルを再利用する必要がある場合、最良の戦略は、React、Svelte、Vueなどのフロントエンドフレームワークを使用している場合はコンポーネントを作成し、Blade、ERB、Twig、Nunjucksなどのテンプレート言語を使用している場合はテンプレートパーシャルを作成することです。

export function VacationCard({ img, imgAlt, eyebrow, title, pricing, url }) {
return (
<div>
<img className="rounded-lg" src={img} alt={imgAlt} />
<div className="mt-4">
<div className="text-xs font-bold text-sky-500">{eyebrow}</div>
<div className="mt-1 font-bold text-gray-700">
<a href={url} className="hover:underline">
{title}
</a>
</div>
<div className="mt-2 text-sm text-gray-600">{pricing}</div>
</div>
</div>
);
}

これで、このコンポーネントを必要な場所にいくつでも使用でき、スタイルを1つの場所で簡単に更新できるように、スタイルの単一の信頼できるソースを維持できます。

カスタムCSSの使用

React や Vue のようなものを使用する代わりに、ERB や Twig のようなテンプレート言語を使用している場合、ボタンほど小さいものに対してテンプレートパーシャルを作成することは、btnのような単純な CSS クラスと比較して、大げさな感じがするかもしれません。

より複雑なコンポーネントの場合は適切なテンプレートパーシャルを作成することを強くお勧めしますが、テンプレートパーシャルが重すぎると感じられる場合は、カスタム CSS を記述してもまったく問題ありません。

btn-primaryクラスがどのように見えるかを次に示します。テーマ変数を使用して、デザインの一貫性を維持しています。

HTML
<button class="btn-primary">Save changes</button>
CSS
@import "tailwindcss";
@layer components {
.btn-primary {
border-radius: calc(infinity * 1px);
background-color: var(--color-violet-500);
padding-inline: --spacing(5);
padding-block: --spacing(2);
font-weight: var(--font-weight-semibold);
color: var(--color-white);
box-shadow: var(--shadow-md);
&:hover {
@media (hover: hover) {
background-color: var(--color-violet-700);
}
}
}
}

ただし、HTML要素が1つだけの場合よりも複雑なものについては、スタイルと構造を1つの場所にカプセル化できるように、テンプレートパーシャルを使用することを強くお勧めします。

スタイルの競合の管理

ユーティリティクラスの競合

同じCSSプロパティをターゲットにする2つのクラスを追加すると、スタイルシートで後に出現するクラスが優先されます。したがって、この例では、flexが実際のclass属性で最後に記述されていても、要素はdisplay: gridを受け取ります。

HTML
<div class="grid flex">
<!-- ... -->
</div>
CSS
.flex {
display: flex;
}
.grid {
display: grid;
}

一般に、同じ要素に競合する2つのクラスを追加することは絶対に避けるべきです。実際に有効にしたいクラスのみを追加してください。

example.jsx
export function Example({ gridLayout }) {
return <div className={gridLayout ? "grid" : "flex"}>{/* ... */}</div>;
}

React や Vue のようなコンポーネントベースのライブラリを使用する場合、多くの場合、スタイルのカスタマイズのために特定のpropsを公開することを意味します。コンシューマーがコンポーネントの外部から追加のクラスを追加できるようにするのではなく、これらのスタイルがしばしば競合するためです。

important モディファイアーの使用

特定のユーティリティクラスを強制的に有効にする必要があり、具体性を管理する他の手段がない場合は、クラス名の最後に!を追加して、すべての宣言を!importantにすることができます。

HTML
<div class="bg-teal-500 bg-red-500!">
<!-- ... -->
</div>
生成されたCSS
.bg-red-500\! {
background-color: var(--color-red-500) !important;
}
.bg-teal-500 {
background-color: var(--color-teal-500);
}

important フラグの使用

既存の複雑なCSSと高い具体性ルールを持つプロジェクトにTailwindを追加する場合は、Tailwind をインポートするときにimportantフラグを使用して、すべてのユーティリティを!importantとしてマークできます。

app.css
@import "tailwindcss" important;
コンパイルされたCSS
@layer utilities {
.flex {
display: flex !important;
}
.gap-4 {
gap: 1rem !important;
}
.underline {
text-decoration-line: underline !important;
}
}

prefix オプションの使用

プロジェクトに Tailwind CSS ユーティリティと競合するクラス名がある場合は、prefixオプションを使用して、Tailwind によって生成されたすべてのクラスと CSS 変数にプレフィックスを付けることができます。

app.css
@import "tailwindcss" prefix(tw);
コンパイルされたCSS
@layer theme {
:root {
--tw-color-red-500: oklch(0.637 0.237 25.331);
}
}
@layer utilities {
.tw\:text-red-500 {
color: var(--tw-color-red-500);
}
}
Copyright © 2025 Tailwind Labs Inc.·商標ポリシー