BLOG

Tailwind CSSをv3からv4へ移行する

Written by mizuishi

INDEX

今回はTailwind CSSのv3からv4にアップグレードするための方法とv3からの変更点を、Tailwind CSSのUpgrade guideページを元に解説します!

アップグレードツールの使用

プロジェクトを v3 から v4 にアップグレードする場合は、アップグレードツールを使用して、面倒な作業の大部分を自動化できます。

$ npx @tailwindcss/upgrade

アップグレードツールが自動化してくれること

アップグレードツールが担ってくれるのは、主に以下の作業です。

  • 依存関係の更新: プロジェクトに必要なパッケージのバージョンを適切に更新してくれます。
  • 設定ファイルの移行: 既存のコンフィグファイル(tailwind.config.jsなど)を新しいバージョンに合わせてCSS形式に自動的に移行してくれます。
  • テンプレートファイルの変更処理: HTMLやJavaScriptなどのテンプレートファイル内の記述も、新しいバージョンに合うように調整してくれます。

これにより、移行プロセス全体の大部分が自動化され、開発者はより重要な作業に集中できるようになります。

ツールを使う上での注意点

このツールを使う上での注意点は以下の通りです。

  • Node.jsのバージョン: アップグレードツールを動かすには、Node.js 20以上が必要です。ツールを実行する前に、ご自身の開発環境が最新の状態になっているか確認しましょう。
  • 新しいブランチでの実行: アップグレードツールを実行する際は、必ず新しいブランチを切ってから試すことを強くおすすめします。これは、万が一予期せぬ問題が発生した場合でも、簡単に元の状態に戻せるようにするためです。
  • 変更内容の確認とテスト: ツールが自動で変更を加えた後には、生成されたコードの差分を注意深く確認し、ブラウザでプロジェクトを徹底的にテストすることが不可欠です。すべての変更が期待通りに反映されているか、機能が正常に動作するかをしっかりと検証しましょう。

複雑なプロジェクトの場合、ツールだけではカバーしきれない部分があり、手作業での微調整が必要になることもあります。しかし、それでもこのツールを使うことで、全体的な作業時間を大幅に節約できることは間違いありません。

手動でアップグレード

PostCSSの使用

v3 ではtailwindcssパッケージは PostCSS プラグインでしたが、v4 では PostCSS プラグインは専用の@tailwindcss/postcssパッケージに存在します。

さらに、v4 ではインポートとベンダー プレフィックスが自動的に処理されるようになったため、プロジェクト内にある場合postcss-importautoprefixerは削除できます。

export default {
  plugins: {
    "postcss-import": {},       // 削除
    tailwindcss: {},            // 削除
    autoprefixer: {},           // 削除
    "@tailwindcss/postcss": {}, // 追加
  },
};

Viteの使用

Vite を使用している場合は、パフォーマンスの向上と最高の開発者エクスペリエンスを実現するために、PostCSS プラグインから新しい専用の Vite プラグインに移行することをお勧めします。

import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite"; // 追加

export default defineConfig({
  plugins: [
    tailwindcss(),                           // 追加
  ],
});

Tailwind CLIの使用

v4では、Tailwind CLIは専用の@tailwindcss/cliパッケージに含まれています。

ビルドコマンドを更新して、新しいパッケージを使用するようにしてください。

npx @tailwindcss/cli -i input.css -o output.css

v3からの変更点

Tailwind CSSの最新バージョンであるv4へのアップグレードは、前述のアップグレードツールを使うことで非常にスムーズに行えます。

しかし、ツールが自動的に処理してくれる変更点の大部分に加え、開発者自身が把握しておくべき重大な変更点もいくつか存在します。

ツールがカバーしきれないケースや、予期せぬ問題が発生した場合に備え、これからご紹介するv4の主要な変更点について、ざっくりとでも把握しておくことは非常に重要です。

ブラウザの要件

Tailwind CSS v4.0 は最新のブラウザ向けに設計されており、Safari 16.4、Chrome 111、Firefox 128 を対象としています。

コア フレームワークの機能には@propertyや などcolor-mix()の最新の CSS 機能に依存しており、Tailwind CSS v4 は古いブラウザでは動作しません。

古いブラウザをサポートする必要がある場合は、今のところバージョン3.4を使用することがおすすめです。

@tailwind ディレクティブ→@import

v4では、v3で使用した@tailwindディレクティブではなく、通常のCSS @importステートメントを使用してTailwindをインポートします。

@tailwind base;@tailwind components;@tailwind utilities;@import "tailwindcss";

非推奨のユーティリティの削除

v3で非推奨となったユーティリティや、数年間ドキュメント化されていないユーティリティはすべて削除されました。

以下は、削除されたユーティリティのリストと最新の代替ユーティリティです。

非推奨

交換

bg-opacity-*

bg-black/50

text-opacity-*

text-black/50

border-opacity-*

border-black/50

divide-opacity-*

divide-black/50

ring-opacity-*

ring-black/50

placeholder-opacity-*

placeholder-black/50

flex-shrink-*

shrink-*

flex-grow-*

grow-*

overflow-ellipsis

text-ellipsis

decoration-slice

box-decoration-slice

decoration-clone

box-decoration-clone

名前が変更されたユーティリティ

v4では、以下のユーティリティの名称を変更され、より一貫性のある予測可能なものになりました。

v3

v4

shadow-sm

shadow-xs

shadow

shadow-sm

drop-shadow-sm

drop-shadow-xs

drop-shadow

drop-shadow-sm

blur-sm

blur-xs

blur

blur-sm

backdrop-blur-sm

backdrop-blur-xs

backdrop-blur

backdrop-blur-sm

rounded-sm

rounded-xs

rounded

rounded-sm

outline-none

outline-hidden

ring

ring-3

shadowradiusblurのスケールの変更

すべてのユーティリティに名前付きの値があるように、デフォルトの shadow、radius、blur のスケールに新しい名前が付きました。
bare(名前なし)」バージョンは後方互換性のために引き続き機能しますが、<utility>-sm ユーティリティは、それぞれの <utility>-xs に更新しない限り、以前とは見た目が異なるので注意が必要です。

これらの変更に合わせてプロジェクトを更新するには、すべてのv3ユーティリティをv4バージョンに置き換えてください。

<input class="shadow-sm" />
↓
<input class="shadow-xs" />

<input class="shadow" />
↓
<input class="shadow-sm" />

outlineユーティリティ名の変更

outline ユーティリティは、borderring ユーティリティとの一貫性を高めるために、デフォルトで outline-width: 1px を設定するようになりました。
さらに、すべての outline-<number> ユーティリティは、デフォルトで outline-stylesolid に設定するため、outline と組み合わせる必要がなくなりました。

<input class="outline outline-2" />
↓
<input class="outline-2" />

outline-none ユーティリティは以前、実際には outline-style: none を設定しておらず、
アクセシビリティのために、強制的な配色モード(forced colors mode)では表示される「見えないアウトライン」が設定されていました。

この挙動をより明確にするために、このユーティリティの名前が outline-hidden に変更され、実際に outline-style: none を設定する新しい outline-none ユーティリティが追加されました。

この変更に対応するためには、既存の outline-none の使用箇所を outline-hidden に置き換えてください。

<input class="focus:outline-none" />
↓
<input class="focus:outline-hidden" />

デフォルトの ring 幅の変更

v3では、ringユーティリティは3pxのリングを追加していました。
しかし、ボーダーやアウトラインとの一貫性を持たせるために、v4では1pxに変更されました。

この変更に対応するためには、既存のringの使用箇所をring-3に置き換えてください。

<input class="ring ring-blue-500" />
↓
<input class="ring-3 ring-blue-500" />

space-betweenセレクター

大規模なページにおける重大なパフォーマンス問題に対処するため、space-x-*およびspace-y-*ユーティリティで使用されるセレクタが変更されました。

/* Before */
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
  margin-top: 1rem;
}

/* Now */
.space-y-4 > :not(:last-child) {
  margin-bottom: 1rem;
}

これらのユーティリティをインライン要素に使用していた場合や、子要素に対して独自にマージンを追加して間隔を調整していた場合、この変更により、プロジェクト内で見た目が変わる可能性があります。

もしこの変更が問題を引き起こす場合は、flexgrid レイアウトに移行し、代わりに gap を使用することをおすすめします。

<div class="space-y-4 p-4">           // 削除
<div class="flex flex-col gap-4 p-4"> // 変更
  <label for="name">Name</label>
  <input type="text" name="name" />
</div>

グラデーション付きのバリアントの使用

v3 では、グラデーションの一部をバリアントで上書きするとグラデーション全体が「リセット」されるため、この例ではto-*ダーク モードで色が黄色ではなく透明になります。

<div class="bg-gradient-to-r from-red-500 to-yellow-400 dark:from-blue-500">
  <!-- ... -->
</div>

v4では、これらの値は保持されるようになりました。
これは、他の Tailwind のユーティリティの動作とより一貫性のある仕様です。

つまり、特定の状態で 3点グラデーション(三色グラデーション)を 2点グラデーションに戻したい場合は、
明示的に via-none を使用して「中間色を解除」する必要があります。

<div class="bg-linear-to-r from-red-500 via-orange-400 to-yellow-400 dark:via-none dark:from-blue-500 dark:to-teal-400">
  <!-- ... -->
</div>

コンテナ構成

v3では、container ユーティリティには centerpadding など、いくつかの設定オプションがありましたが、これらはv4では廃止されました。

バージョン4で container ユーティリティをカスタマイズするには、@utility ディレクティブを使って拡張してください。

@utility container {
  margin-inline: auto;
  padding-inline: 2rem;
}

デフォルトの境界線の色

v3では、border-* および divide-* ユーティリティはデフォルトで設定された gray-200 の色が使用されていました。
v4では、ブラウザのデフォルトに合わせるために、 currentColor に変更されました。

この変更に対応するには、border-*divide-* ユーティリティを使う箇所では、必ず色を明示的に指定するようにしてください。

<div class="border border-gray-200 px-2 py-3 ...">
  <!-- ... -->
</div>

あるいは、以下のテーマ変数を CSS に追加して、v3の動作を維持することもできます。

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentColor);
  }
}

デフォルトのリング幅と色

ring ユーティリティの幅を 3px から 1px に変更、デフォルトの色を blue-500 から currentColor に変更されました。
これは、border-*divide-*、および outline-* ユーティリティとの一貫性を高めるためです。

これらの変更に対応するには、既存の ring の使用箇所を ring-3 に置き換えてください。

<button class="focus:ring ..."> // 削除
<button class="focus:ring-3 ...">
  <!-- ... -->
</button>

次に、ring-blue-500デフォルトのリングの色に応じて、任意の場所に追加してください。

<button class="focus:ring-3 focus:ring-blue-500 ...">
  <!-- ... -->
</button>

あるいは、以下のテーマ変数を CSS に追加して、v3の動作を維持することもできます。

@theme {
  --default-ring-width: 3px;
  --default-ring-color:
 var(--color-blue-500);
}

ただし、これらの変数は互換性の理由からのみサポートされており、Tailwind CSS v4 の慣用的な使用法とは見なされないことに注意してください。

Preflightの変更

v4の Preflight(ベーススタイル)で、いくつか小さな変更を加えられました。

新しいデフォルトのプレースホルダーの色
v3では、プレースホルダーのテキストはデフォルトで設定された gray-400 の色が使用されていました。
v4ではこれを簡素化し、現在のテキストカラーの 50% 不透明度で表示するように変更されました。

この変更はほとんど気づかないかもしれません(場合によってはプロジェクトの見た目が良くなることもあります)。
しかし、もしバージョン3の挙動を維持したい場合は、以下のテーマ変数を CSS に追加してください。

@layer base {
  input::placeholder,
  textarea::placeholder {
    color: var(--color-gray-400);
  }
}

ボタンはデフォルトのカーソルを使用

ボタンは、デフォルトのブラウザ動作に合わせて、これまでの cursor: pointer ではなく、cursor: default を使用するようになりました。

もし引き続きデフォルトで cursor: pointer を使いたい場合は、以下のベーススタイルを CSS に追加してください。

@layer base {
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;  }
}

ダイアログの余白を削除

<dialog> 要素のマージンをリセットするようになり、他の要素のリセット方法と一貫性を持ちました。

もし <dialog> をデフォルトで中央寄せにしたい場合は、以下の CSS をプロジェクトに追加してください。

@layer base {
  dialog {
    margin: auto;
  }
}

接頭辞の使用

プレフィックスは現在、バリアントのような形式になり、クラス名の常に先頭に配置されるようになりました。

<div class="tw:flex tw:bg-red-500 tw:hover:bg-red-600">
  <!-- ... -->
</div>

プレフィックスを使用する場合でも、プレフィックスを使用していないときと同じようにテーマ変数を設定する必要があります。

@import "tailwindcss" prefix(tw);

@theme {
  --font-display: "Satoshi", "sans-serif";

  --breakpoint-3xl: 120rem;

  --color-avocado-100: oklch(0.99 0 0);
  --color-avocado-200: oklch(0.98 0.04 113.22);
  --color-avocado-300: oklch(0.94 0.11 115.03);
  /* ... */
}

生成された CSS 変数には、プロジェクト内の既存の変数との競合を避けるためのプレフィックスが含まれます

:root {
  --tw-font-display: "Satoshi", "sans-serif";

  --tw-breakpoint-3xl: 120rem;

  --tw-color-avocado-100: oklch(0.99 0 0);
  --tw-color-avocado-200: oklch(0.98 0.04 113.22);
  --tw-color-avocado-300: oklch(0.94 0.11 115.03)
  /* ... */
}

カスタムユーティリティの追加

v3では、@layer utilities@layer components 内で定義したカスタムクラスは、Tailwind によって本物のユーティリティクラスとして認識され、hoverfocuslg などのバリアントも自動的に適用されていました。
ただし、@layer components のクラスは生成されるスタイルシート内で常に先に読み込まれていました。

v4では、ネイティブのカスケードレイヤーを使用するようになり、@layer ルールをハイジャックしなくなったため、これに代わるものとして @utility API が導入されました。

@layer utilities {
  .tab-4 {
    tab-size: 4;
  }
}
↓
@utility tab-4 {
  tab-size: 4;
}

カスタムユーティリティは、定義しているプロパティの数に基づいてソートされるようになりました。
つまり、.btn のようなコンポーネントユーティリティは、追加の設定なしに他の Tailwind ユーティリティによって上書きされる可能性があります。

@layer components {
  .btn {
    border-radius: 0.5rem;
    padding: 0.5rem 1rem;
    background-color: ButtonFace;
  }
}
↓
@utility btn {
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  background-color: ButtonFace;
}

バリアントの重ね順

v3では、重ねられたバリアントは右から左に適用されていましたが、v4では、CSSの文法により近づけるために左から右に適用されるように変更されました。

この変更に対応するには、プロジェクト内で順序が重要な重ねバリアントの順番を逆にしてください。

<ul class="py-4 first:*:pt-0 last:*:pb-0"> // 削除
<ul class="py-4 *:first:pt-0 *:last:pb-0"> // 変更
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

おそらく、こうしたケースはほとんど、または全くないと思います。
直接の子セレクタバリアント(*)やタイポグラフィプラグインのバリアント(prose-headings)が、使用されている可能性が最も高いですが、それも他のバリアントと重ねて使っている場合に限られます。

arbitrary valuesでの変数の扱い

v3では、CSS変数を var() を使わずに任意の値として使用できましたが、最近のCSSのアップデートにより、これが曖昧になることが多くなったため、v4ではこの書き方を、角括弧 ([]) ではなく丸括弧 (()) を使う形式に変更されました。

この変更に対応するには、旧来の変数の省略記法を新しい省略記法に置き換えてください。

<div class="bg-[--brand-color]"></div> // 削除
<div class="bg-(--brand-color)"></div> // 変更

モバイルでのホバースタイル

v4では、hover バリアントはプライマリ入力デバイスがホバー操作をサポートしている場合にのみ適用されるように更新されました。

@media (hover: hover) {
  .hover\:underline:hover {
    text-decoration: underline;
  }
}

この変更は、タッチデバイスでのタップによってホバー状態が発生することに依存してサイトを構築している場合、問題を引き起こす可能性があります。
もしこれが問題であれば、hover バリアントを、旧来の実装を使う独自のバリアントで上書きすることができます。

@custom-variant hover (&:hover);

タッチデバイスには本来ホバーの機能がないため一般的には、ホバー機能はあくまで ユーザー体験の向上(エンハンスメント) として扱い、サイトの基本動作がホバーに依存しないようにすることをおすすめします。

outline-colorのトランジション

transition および transition-color ユーティリティに、outline-color プロパティが新たに含まれるようになりました。

そのため、フォーカス時にカスタムカラーのアウトラインを追加している場合、デフォルトの色からカラートランジションが発生するのが見られるようになります。

これを避けるには、アウトラインの色を常に(無条件に)設定するか、両方の状態(通常時とフォーカス時)で明示的に色を設定してください。

<button class="transition hover:outline-2 hover:outline-cyan-500"></button> // 削除
<button class="outline-cyan-500 transition hover:outline-2"></button>       // 変更

コアプラグインの無効化

v3では、corePlugins オプションを使ってフレームワーク内の特定のユーティリティを完全に無効化することができましたが、v4ではこの方法はサポートされなくなりました。

theme()関数の使用

v4ではテーマのすべての値に対して CSS 変数が含まれているため、可能な限り theme() 関数の代わりにこれらの CSS 変数を使うことをおすすめします。

.my-class {
  background-color: theme(colors.red.500); // 削除
  background-color: var(--color-red-500);  // 変更
}

CSS変数が使えないメディアクエリなど、それでも theme() 関数を使う必要がある場合は、旧来のドット表記の代わりに CSS変数名を使うべきです。

@media (width >= theme(screens.xl)) {      // 削除
@media (width >= theme(--breakpoint-xl)) { // 変更
  /* ... */
}

JavaScript設定ファイルの使用

JavaScript の設定ファイルは後方互換性のために引き続きサポートされていますが、バージョン4では自動的に検出されなくなりました。

それでも JavaScript 設定ファイルを使いたい場合は、@config ディレクティブを使って明示的に読み込む必要があります。

@config "../../tailwind.config.js";

JavaScript ベースの設定ファイルで使われていた corePluginssafelist、および separator オプションは、バージョン4.0ではサポートされていません。

最後に

長くなりましたが、基本的なTailwind CSSのアップグレード方法と、v3→v4への変更点をUpgrade guideページを元に説明しました。

プロジェクトでv3→v4へ変更する際の一助になれば幸いです。

参考

https://tailwindcss.com/

https://tailwindcss.com/docs/upgrade-guide