ブログ一覧

Tailwind v3 で node_modules の CSS が @layer エラーになる原因

更新: Web開発者向け

Astro サイトに Tailwind CSS v3 を PostCSS 経由(postcss.config.cjs + tailwind.config.cjs)で導入したところ、自分のコードには一切触れていない管理画面が 500 を返すようになり、本番ビルドも通らなくなるという現象に当たりました。

サイトは管理画面同梱型の CMS「EmDash」(Astro 製)の上に構築していて、壊れたのは、フレームワークがビルド済みの完成品として持っている管理画面の CSS です。

本記事では、Tailwind v3 の PostCSS 構成が「プロジェクトを通るすべての CSS」を処理してしまう問題と、@layer の解釈衝突という壊れ方、そして Tailwind v4(@tailwindcss/vite)への移行による解決、あわせて v3 → v4 で実際に必要だったクラス名の書き換えをまとめます。

前提: Astro + Vite のプロジェクトで確認。Tailwind v3 の PostCSS 構成と、ネイティブの CSS カスケードレイヤー(@layer)を使う第三者 CSS が同居する構成全般で起こります。

なぜ他人の CSS が壊れるのか

PostCSS の設定ファイル(postcss.config.cjs)はプロジェクト全体の CSS に適用されます。Vite のパイプラインを通る CSS は、自分が書いた global.css だけでなく、node_modules 由来のビルド済み CSS も含めて、全部が PostCSS プラグイン(= Tailwind v3)を通過します。

ここで衝突するのが @layer です。

  • CSS 標準の @layer はカスケードレイヤー。モダンな UI ライブラリのビルド済み CSS は普通に使っています(@layer base { ... } など)
  • Tailwind v3 は同じ @layer を自前のディレクティブとして解釈します。v3 にとって @layer base は「@tailwind base で展開される場所に挿入する宣言」であり、対応する @tailwind base がないファイルに現れると、こういうエラーで止まります
`@layer base` is used but no matching `@tailwind base` directive is present.

つまり、標準 CSS として完全に正しい第三者のファイルが、Tailwind v3 の PostCSS を通った瞬間に不正になるわけです。開発サーバーでは管理画面の CSS 配信が 500 になり、本番ビルドはこのエラーで落ちました。

v3 でこのエラーを回避するには、PostCSS の対象からそのファイルを外す設定を書くことになり、かなり不毛です。

解決: Tailwind v4 の Vite プラグインに移行する

Tailwind v4 では @layer の扱いと導入方法が設計から変わっています。

  • @layer の自前解釈をやめ、ネイティブのカスケードレイヤーをそのまま使うようになった。第三者 CSS の @layer base は標準 CSS のまま扱われる
  • 導入方法も PostCSS 設定から Vite プラグイン(@tailwindcss/vite)に変わり、プロジェクト全体の CSS を処理対象にしない

移行はファイル 3 つの置き換えで済みました。

// astro.config.mjs
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
	vite: {
		plugins: [tailwindcss()],
	},
});
/* global.css — v3 の @tailwind 3行が @import 1行になる */
@import "tailwindcss";
@plugin "@tailwindcss/forms";

postcss.config.cjs と tailwind.config.cjs は削除します(v4 は設定も CSS 内の @theme に書く方針で、シンプルな構成なら設定ファイル自体が不要です)。これで管理画面の 500 も本番ビルドのエラーも解消しました。

v3 → v4 で実際に書き換えたクラス名

v4 は既存クラスの一部を改名しています。移行で実際に引っかかったものだけ挙げます(網羅は公式アップグレードガイドを参照)。

  • bg-gradient-to-r など → bg-linear-to-r
  • rounded(無印) → rounded-sm
  • shadow-sm → shadow-xs
  • backdrop-blur-sm → backdrop-blur-xs
  • !leading-tight(important 前置) → leading-tight!(接尾辞に変更)

サイズ系は「一段ずれた」(旧 sm が新 xs に相当)と覚えると楽です。important 修飾子の前置 → 接尾辞は grep で機械的に拾えます。

なお移行後に旧環境と getComputedStyle で突き合わせたところ、色が rgb → oklab 表記に変わっている箇所がありますが、これは v4 が内部のカラー処理を近代化した結果の表記差で、実際の色は同一でした。ピクセル比較で「色が変わった!」と焦らないように。

Tailwind 移行の話としては、そもそも Vuetify から Tailwind に乗り換えたときの記録「さようならVuetify。ようこそTailwind CSS」、CSS 最適化全般は「CSSの最適化アプローチ」も参考にどうぞ。

まとめ

  • Tailwind v3 の PostCSS 構成は、node_modules のビルド済み CSS を含むすべての CSS を処理対象にする
  • v3 は @layer を自前ディレクティブとして解釈するため、ネイティブのカスケードレイヤーを使う標準準拠の第三者 CSS がエラーになる
  • Tailwind v4 + @tailwindcss/vite へ移行すると、Tailwind がネイティブ @layer を解釈しなくなり、エラーが出なくなる。設定ファイルも減る
  • v4 のクラス改名(bg-linear-to-*、サイズ一段ずれ、important 接尾辞化)は grep で機械的に対応できる。oklab 表記への変化は見た目同一

この記事をシェア