Tailwind CSS とは、p-4 や text-center のような小さな役割のクラス(ユーティリティクラス)を HTML に並べてデザインする CSS フレームワークです。CSS ファイルを行き来せずに見た目を組み立てられ、実際に使ったクラスだけが CSS に出力されるので、ファイルも小さく保てます。

Tailwind CSS は 2025年1月の v4 で、導入方法とカスタマイズ方法が大きく変わりました。CSS に @import "tailwindcss"; と1行書くだけで始められ、設定は tailwind.config.js ではなく CSS の @theme に書きます。この記事では、2026年9月時点の最新版 v4.3.3 を npm で入れて実際に CSS をビルドし、生成された CSS の中身を見ながら、基本の使い方から「動的なクラス名が生成されない」といったつまずきまでを解説します。

Tailwind CSS の使い方 早見表

やりたいこと 書き方 生成される CSS(v4.3.3 の実際の出力)
余白 p-4 / px-4 / mt-2 padding: calc(var(--spacing) * 4);
文字の大きさ・太さ text-2xl / font-bold font-size: var(--text-2xl);
色 bg-white / text-gray-900 background-color: var(--color-white);
透明度つきの色 bg-black/50 color-mix(in oklab, var(--color-black) 50%, transparent)
画面幅で切り替え md:p-8 @media (width >= 48rem) { ... }
マウスを乗せたとき hover:bg-blue-700 @media (hover: hover) { ...:hover }
ダークモード dark:bg-gray-900 @media (prefers-color-scheme: dark)
決まった値以外 mt-[13px] / text-[#1da1f2] margin-top: 13px;
CSS 変数を使う bg-(--brand) background-color: var(--brand);
色やブレークポイントを追加 CSS の @theme { --color-brand-500: ... } bg-brand-500 が使えるようになる
独自のユーティリティ @utility tab-4 { tab-size: 4; } tab-4 が使えるようになる

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Tailwind CSS 使い方|v4の導入からつまずき対策まで実行結果つき」

検証した環境

項目 バージョン
tailwindcss / @tailwindcss/cli 4.3.3(npm view tailwindcss version で確認した最新版)
@tailwindcss/vite 4.3.3(Vite 8.3.1 で確認)
Node.js 22.22.2

v4 は最新の CSS 機能(@property、color-mix() など)を使うため、対応ブラウザは Safari 16.4 以上、Chrome 111 以上、Firefox 128 以上です(公式アップグレードガイドより)。これより古いブラウザに対応する必要がある場合は、v3.4 を使い続ける選択肢もあります。

導入方法:3通り

どの方法でも、CSS に書くのは @import "tailwindcss"; の1行だけです。v3 で必要だった tailwind.config.js の作成や、content にファイルのパスを並べる設定は不要になりました(使っているクラスはプロジェクトのファイルから自動で探されます)。

方法 入れるパッケージ 向いている場面
CLI tailwindcss @tailwindcss/cli 静的な HTML、ビルドツールがない構成
Vite プラグイン tailwindcss @tailwindcss/vite React・Vue・Svelte など Vite を使う構成(公式ドキュメントで最初に紹介)
PostCSS プラグイン tailwindcss @tailwindcss/postcss Next.js など PostCSS を使う構成

CLI で使う

npm install tailwindcss @tailwindcss/cli
/* src/input.css */
@import "tailwindcss";
npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch
<link href="./output.css" rel="stylesheet">

実際にビルドしたときの出力です。

≈ tailwindcss v4.3.3

Done in 59ms

--watch を付けると、HTML を保存するたびに CSS が作り直されます。本番用には --minify を付けて圧縮します。

Vite で使う

npm install -D vite tailwindcss @tailwindcss/vite
// vite.config.js
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [tailwindcss()],
});
/* style.css */
@import "tailwindcss";

npx vite build の実際の出力です。class="text-3xl font-bold underline" だけを使った HTML で、CSS は 4.77 kB(gzip で 1.63 kB)でした。

dist/index.html                 0.24 kB │ gzip: 0.20 kB
dist/assets/index-DqPXTuJK.css  4.77 kB │ gzip: 1.63 kB

✓ built in 115ms

PostCSS で使う(Next.js など)

// postcss.config.mjs
const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

export default config;

Next.js 16 の create-next-app で Tailwind を選ぶと、この設定と @import "tailwindcss"; で始まる globals.css が最初から作られます(実際に生成して確認しました)。autoprefixer や postcss-import は、v4 では Tailwind 側が引き受けるので不要です。

ユーティリティの基本

1つのクラスが、だいたい1つの CSS の指定に対応します。数値は「4 = 1rem(16px)」のように、--spacing(既定 0.25rem)の倍数です。

分類 よく使うクラス 意味
余白 p-4 px-6 py-2 m-auto mt-8 gap-4 padding / margin / gap
サイズ w-full w-64 max-w-3xl h-screen size-10 幅・高さ(size-* は両方)
文字 text-sm text-2xl font-bold leading-relaxed text-center 大きさ・太さ・行間・揃え
色 text-gray-900 bg-white border-gray-200 bg-blue-600/80 文字色・背景・枠線・透明度
枠・角丸・影 border rounded-lg shadow-md 枠線・角丸・影
並べ方 flex items-center justify-between grid grid-cols-3 Flexbox / Grid
表示 hidden block inline-flex display
<div class="mx-auto max-w-3xl p-4 md:p-8">
  <h1 class="text-2xl font-bold md:text-4xl">こんにちは</h1>
  <button class="rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">送信</button>
</div>

色の値は var(--color-blue-600) のように CSS 変数として出力されます。v4 では既定のテーマがすべて CSS 変数なので、自分の CSS からも var(--color-blue-600) と書いて同じ色を使えます。

レスポンシブ:sm: md: lg: は「その幅以上」

Tailwind のレスポンシブは「スマホを基本に書き、広い画面で上書きする」考え方(モバイルファースト)です。md:p-8 は「幅 48rem(768px)以上のとき p-8」という意味で、実際の出力も次のとおりでした。

@media (width >= 48rem) {
  .md\:p-8 {
    padding: calc(var(--spacing) * 8);
  }
}
接頭辞 最小幅 目安
(なし) 0 スマホ
sm: 40rem(640px) 大きめのスマホ
md: 48rem(768px) タブレット
lg: 64rem(1024px) ノートPC
xl: 80rem(1280px) デスクトップ
2xl: 96rem(1536px) 大画面
  • sm: は「スマホ用」ではありません。スマホ向けは接頭辞なしで書きます
  • 「この幅未満だけ」にしたいときは max-md:hidden のように max- を付けます
  • 親要素の幅で切り替えるコンテナクエリーも標準で使えます(親に @container、子に @md:flex-row)

ブレークポイントは @theme で追加できます。--breakpoint-3xl: 120rem; を追加して 3xl:text-6xl を使うと、@media (width >= 120rem) が生成されました。

状態:hover: focus: など

接頭辞 いつ効くか
hover: マウスを乗せたとき(v4 ではホバーできる端末のみ)
focus: / focus-visible: フォーカス時 / キーボード操作でのフォーカス時
active: 押している間
disabled: 無効のとき
first: last: odd: 最初・最後・奇数番目の要素
group-hover: 親(group クラス)にマウスを乗せたとき
peer-checked: 兄弟(peer クラス)がチェックされたとき
aria-expanded: data-[state=open]: ARIA 属性や data 属性の値

v4 の hover: は、実際の出力で @media (hover: hover) の中に入っていました。

@media (hover: hover) {
  .hover\:bg-blue-700:hover {
    background-color: var(--color-blue-700);
  }
}

これにより、スマホでタップしたあとにホバーの見た目が残る現象が起きにくくなっています。タップ時の見た目も付けたいときは active: を併用します。

ダークモード

既定の dark: は、OS の設定(prefers-color-scheme)に合わせて切り替わります。実際の出力は次のとおりです。

@media (prefers-color-scheme: dark) {
  .dark\:bg-gray-900 {
    background-color: var(--color-gray-900);
  }
}

サイト内のボタンで切り替えたい場合は、CSS に @custom-variant を1行足します。

@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
<html class="dark">
  <div class="bg-white dark:bg-black">...</div>
</html>

このときの実際の出力です。メディアクエリーではなく、.dark クラスの有無で切り替わるようになりました。

.dark\:bg-black:where(.dark, .dark *) {
  background-color: var(--color-black);
}

data-theme="dark" で切り替えたい場合は @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); と書きます。v3 の darkMode: 'class' の設定は、v4 ではこの @custom-variant に置き換わります。

任意値:決まった値以外を使う

テーマにない値は、角かっこ [...] で直接書けます。

書き方 実際の出力
mt-[13px] margin-top: 13px;
text-[#1da1f2] color: #1da1f2;
grid-cols-[200px_1fr] grid-template-columns: 200px 1fr;(空白は _)
bg-(--brand) background-color: var(--brand);

CSS 変数を使うときの書き方が v4 で変わりました。v3 の書き方 bg-[--brand] を v4.3.3 で試すと、エラーにはならず、次のような効かない CSS が出力されました。

.bg-\[--brand\] {
  background-color: --brand;   /* var() がないので無効 */
}
.bg-\(--brand\) {
  background-color: var(--brand);   /* v4 の正しい書き方 */
}

v4 では CSS 変数は丸かっこ bg-(--brand) で書きます。任意値を何度も使うようなら、@theme にトークンとして登録するほうが、デザインの統一感を保てます。

@theme でカスタマイズする(tailwind.config.js は不要)

@import "tailwindcss";

@theme {
  --color-brand-500: oklch(0.62 0.19 250);
  --font-display: "Noto Sans JP", sans-serif;
  --breakpoint-3xl: 120rem;
}

@theme に書いた変数から、対応するクラスが自動で作られます。上の例では bg-brand-500・text-brand-500・font-display・3xl: が使えるようになり、実際に .bg-brand-500 { background-color: var(--color-brand-500); } が生成されました。

変数の名前空間 作られるクラスの例
--color-* bg-* text-* border-* など
--font-* font-*(書体)
--text-* text-*(文字サイズ)
--font-weight-* font-bold など
--spacing p-* m-* w-* などの基準値
--breakpoint-* sm: md: などのレスポンシブ
--radius-* rounded-*
--shadow-* shadow-*
--animate-* animate-*
  • 既定の色を全部消して自分の色だけにする:--color-*: initial; を書いてから定義する
  • ほかの変数を参照する:@theme inline { --font-sans: var(--font-inter); }(Next.js のひな形もこの形)
  • @theme と :root の違い:@theme はクラスを作る設計トークン、:root はただの CSS 変数
  • どうしても JS の設定ファイルを使いたい場合は @config "./tailwind.config.js"; で読み込めます(corePlugins・safelist・separator は非対応)

v3 からの主な変更点

公式アップグレードガイドに沿って、影響の大きいものをまとめました。自動変換ツール npx @tailwindcss/upgrade(Node.js 20 以上)で大部分を書き換えられます。新しいブランチで実行し、差分を確認するのがおすすめです。

項目 v3 v4
CSS の読み込み @tailwind base; など3行 @import "tailwindcss";
設定 tailwind.config.js CSS の @theme
対象ファイルの指定 content: [...] 自動検出(@source で追加)
パッケージ tailwindcss のみ @tailwindcss/cli / vite / postcss に分離
独自ユーティリティ @layer utilities { .x {} } @utility x { }
important !flex flex!
CSS 変数の任意値 bg-[--x] bg-(--x)
透明度 bg-opacity-50 bg-black/50
影・角丸・ぼかし shadow-sm / shadow shadow-xs / shadow-sm(1段ずつずれた)
outline-none 見えないアウトライン outline-hidden に改名
ring 3px・青 1px・現在の文字色。3px は ring-3
既定の枠線の色 gray-200 現在の文字色(border-gray-200 などを明示)
ボタンのカーソル pointer default
バリアントの重ね順 右から左 左から右(*:first:pt-0)
Sass / Less 併用できた 併用しない前提

実際に試して分かったこと

v3 の3行(@tailwind base; など)を v4.3.3 でビルドすると、エラーにはならずに bg-red-500 も p-4 も生成されませんでした(出力はライセンスのコメント1行だけ)。テーマ(色や余白の値)が読み込まれないためです。「アップグレードしたら見た目が全部消えた」というときは、まず CSS の先頭行を確認します。

bg-opacity-50 は何も生成されませんでした。一方 ring の出力は calc(1px + ...) と currentcolor で、ガイドどおり「1px・文字色」になっていました。また、v4 の shadow と shadow-sm は同じ値が出力されました。v3 の shadow-sm の見た目は、v4 では shadow-xs です。

v4.3.3 の CLI には、クラス名を正式な書き方にそろえる canonicalize コマンドもありました。

$ npx tailwindcss canonicalize "!flex flex-grow flex-shrink-0 overflow-ellipsis"
flex! grow shrink-0 text-ellipsis

@apply の使いどころ

@apply は、ユーティリティクラスの中身を自分の CSS の中に展開する機能です。

@import "tailwindcss";

@layer components {
  .btn-primary {
    @apply rounded-lg bg-blue-600 px-4 py-2 font-semibold text-white hover:bg-blue-700;
  }
}

実際の出力です。hover: も、ホバー対応端末向けのメディアクエリーつきで展開されました。

@layer components {
  .btn-primary {
    border-radius: var(--radius-lg);
    background-color: var(--color-blue-600);
    padding-inline: calc(var(--spacing) * 4);
    padding-block: calc(var(--spacing) * 2);
    font-weight: var(--font-weight-semibold);
    color: var(--color-white);
    &:hover {
      @media (hover: hover) {
        background-color: var(--color-blue-700);
      }
    }
  }
}
@apply が向いている場面 部品化が向いている場面
CMS や Markdown から出力される HTML にクラスを付けられない React・Vue などで部品を作れる
外部ライブラリの要素に見た目を合わせたい 同じ見た目が複数の場所に出てくる
ごく少数の、全体で共通の基本スタイル 見た目に「種類」や「サイズ」のバリエーションがある

@apply を多用すると、結局ふつうの CSS を書くのと変わらなくなり、Tailwind の「HTML を見れば見た目が分かる」良さが薄れます。繰り返しの解消は、まず次の「部品化」で考えるのがおすすめです。

なお、Vue や Svelte の <style> ブロック、CSS Modules の中で @apply を使うときは、先頭に @reference "../app.css"; を書いて、テーマを参照させます。

クラスが長くなる問題への対処

Tailwind で長いクラスの列が気になったら、まずは「部品(コンポーネント)にまとめる」のが基本です。

// Button.jsx:見た目のバリエーションを1か所で管理する
const base = "inline-flex items-center rounded-lg font-semibold focus-visible:outline-2 focus-visible:outline-offset-2";
const variants = {
  primary: "bg-blue-600 text-white hover:bg-blue-700",
  secondary: "bg-white text-gray-900 border border-gray-300 hover:bg-gray-50",
};
const sizes = {
  sm: "px-3 py-1.5 text-sm",
  md: "px-4 py-2 text-base",
};

export function Button({ variant = "primary", size = "md", className = "", ...props }) {
  return <button className={`${base} ${variants[variant]} ${sizes[size]} ${className}`} {...props} />;
}
対処 内容
部品にまとめる ボタン・カードなどを1つの部品にし、使う側は <Button variant="primary"> と書く
バリエーションをオブジェクトで持つ variants のように完全なクラス名を並べる(次の章の対策にもなる)
クラスの並び順をそろえる 公式の Prettier プラグイン prettier-plugin-tailwindcss で自動整列
重複・衝突を解消する tailwind-merge で p-2 と p-4 のような衝突を後勝ちに整理
条件付きのクラス clsx などで条件ごとに完全なクラス名を足す
エディターの補完 公式の VS Code 拡張「Tailwind CSS IntelliSense」

よくあるつまずき:動的なクラス名が生成されない

Tailwind は、ファイルを「ただの文字列」として読み、クラス名らしい文字列を探して CSS を作ります。そのため、JavaScript で文字列を組み立てたクラス名は見つけられません。

直す前:クラス名を組み立てる

// Badge.jsx
export function Badge({ color }) {
  // color には "purple" や "amber" が入る想定
  return <span className={`bg-${color}-500 text-white`}>NEW</span>;
}

このファイルだけを対象にビルドした実際の出力です。text-white は生成されましたが、bg-purple-500 も bg-amber-500 も生成されていません。

@layer utilities {
  .text-white {
    color: var(--color-white);
  }
}

画面では「背景色が付かない」という症状になります。エラーは出ないため、気づきにくいのが特徴です。

直した後:完全なクラス名を書いておき、選ぶ

const badgeColors = {
  purple: "bg-purple-500",
  amber: "bg-amber-500",
};

export function Badge({ color }) {
  return <span className={`${badgeColors[color]} text-white`}>NEW</span>;
}
@layer utilities {
  .bg-amber-500 {
    background-color: var(--color-amber-500);
  }
  .bg-purple-500 {
    background-color: var(--color-purple-500);
  }
  .text-white {
    color: var(--color-white);
  }
}

クラス名をソースコードのどこかに「完全な形」で書いておけば、生成されます。

逆に、コメントに書いた文字列でも生成される

同じ仕組みの裏返しで、次のようなファイルではコメントの中の bg-lime-300 も生成されました。

// TODO: あとで bg-lime-300 に変える
const msg = "text-center";
.bg-lime-300 { background-color: var(--color-lime-300); }
.text-center { text-align: center; }

実害はほぼありませんが、「使っていないはずのクラスが CSS にある」理由はこれです。

どうしても組み立てたいとき:@source inline

CMS から色名が届くなど、ソースに書けない場合は、CSS 側で生成を指示(セーフリスト)できます。

@import "tailwindcss";
@source inline("bg-{purple,amber}-500");

実際に bg-amber-500 と bg-purple-500 が生成されました。{100..900..100} のような範囲指定や、{hover:,} でバリアント付きの指定もできます。v3 の safelist 設定は、v4 ではこの @source inline() に置き換わります。

そのほかのつまずき

症状 原因 対処
特定のフォルダーのクラスが効かない .gitignore に含まれるファイルや node_modules は自動検出の対象外 @source "../node_modules/@my/ui"; で追加
アップグレード後に見た目が全部消えた @tailwind base; などの v3 の書き方のまま @import "tailwindcss"; にする
枠線の色が濃くなった v4 の既定の枠線色は文字色 border-gray-200 などを明示
ボタンのカーソルが矢印になった v4 の Preflight で cursor: default に cursor-pointer を付ける
スマホでホバーの見た目が出ない v4 の hover: はホバーできる端末のみ active: を併用
bg-[--brand] が効かない v4 では CSS 変数は丸かっこ bg-(--brand)
自作クラスに hover: が付かない @layer utilities に書いている @utility で定義する
Sass と一緒に使えない v4 はプリプロセッサと併用しない前提 ネストや変数は CSS 標準の機能で書く

よくある質問

Q. CDN の <script> タグで使ってもいいですか? A. ブラウザ上で CSS を作る Play CDN は、試作や学習向けです。本番のサイトでは、CLI・Vite・PostCSS のいずれかでビルドした CSS を配信すると、表示が速く安定します。

Q. tailwind.config.js は、もう使えないのですか? A. @config "./tailwind.config.js"; で読み込めば使えます。ただし corePlugins・safelist・separator は非対応です。新しく始めるなら、CSS の @theme に書くのが v4 の標準です。

Q. インラインスタイルと何が違うのですか? A. インラインスタイル(style="...")では、hover: などの状態、md: などのレスポンシブ、ダークモードが書けません。また Tailwind はテーマに沿った決まった値から選ぶので、余白や色がそろいやすくなります。

Q. 生成される CSS はどれくらいの大きさですか? A. 使ったクラスだけが出力されます。この記事の Vite の例(3クラス)は 4.77 kB(gzip 1.63 kB)で、その多くはブラウザごとの差をならす基本スタイル(Preflight)でした。クラスを増やしても、1クラスあたりの増え方はわずかです。

まとめ

  • Tailwind CSS v4 は CSS に @import "tailwindcss"; と書くだけで始められる。導入は CLI・Vite・PostCSS の3通り
  • カスタマイズは CSS の @theme。tailwind.config.js と content の設定は不要
  • レスポンシブは モバイルファースト(md: は「768px 以上」)、hover: は ホバーできる端末のみに効く
  • ダークモードは既定で OS 連動。手動切り替えは @custom-variant dark
  • v3 からの移行は npx @tailwindcss/upgrade。!flex → flex!、bg-[--x] → bg-(--x)、shadow-sm → shadow-xs に注意
  • 長いクラスは 部品化で整理し、@apply は HTML にクラスを付けられない場面に絞る
  • 動的に組み立てたクラス名は生成されない。完全なクラス名を書き、どうしても必要なら @source inline()

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Tailwind CSS 使い方|v4の導入からつまずき対策まで実行結果つき」

株式会社RJCでは、Tailwind CSS のようなフロントエンドの道具も、実際に手を動かして確かめながら、仲間と一緒に学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?