💫

既存プロジェクトを Tailwind CSS に段階的にマイグレーションする方法

2024/07/01に公開

not Tailwind CSS プロジェクトを Tailwind CSS に移行する機会があったのでアプローチを紹介します。

ポイント

  1. ベースが16px ではない場合、tailwind-pixel-perfect-preset で rem to px を行い、 Taiwlind CSS のサイズ指定(h-4など)を踏襲する
  2. tw- prefix をつけて既存スタイルの競合を回避する
  3. Tailwind CSS のノーマライズスタイルを無効にして既存スタイルへの影響を回避する
  4. ノーマライズスタイルをスコープ化して既存スタイルへの影響を防ぎつつ Tailwind CSS 正確なスタイルを実現する
tailwind.config.js
import {
  isolateForComponents,
  scopedPreflightStyles,
} from "tailwindcss-scoped-preflight";

/** @type {import('tailwindcss').Config} */
module.exports = {
  presets: [require("@rise8/tailwind-pixel-perfect-preset")], // 1
  darkMode: ["class"],
  content: ["./src/**/*.{ts,tsx}"],
  prefix: "tw-", // 2
  corePlugins: {
    preflight: false, // 3
  },
  theme: {
    // ...
    extend: {
      // shadcn/ui のスタイルなど
    },
  },
  plugins: [
    require("tailwindcss-animate"),
    // 4
    scopedPreflightStyles({
      isolationStrategy: isolateForComponents(".tw"),
    }),
  ],
};

Tailwind CSS のスタイルは既存のスタイルの下に配置し、優先されるようにします。とはいえ実態は CSS 変数とプレフィックス付きのユーティリティクラスだけなので既存スタイルのスタイルを上書きして表示を崩す恐れはありません。

実装イメージ

tw をつけたら部分的に Tailwind CSS のノーマライズスタイルが適用されます。 tw- プレフィックスをつけることで Taiwind CSS を使用できます。

<button className="tw tw-text-sky-500 dark:tw-text-white">ボタン</button>

ダークモード対応

body に tw-dark をつけ外しすれば通常通りダークモードが適用されます。この辺りはテーマ管理ライブラリにより実装が変わるのでそちらを参照してください。shadcn/ui を導入している場合、ダークモードのセクションを .tw-dark に変更してください。

globals.css
.tw-dark {
  --background: 0 0% 3.9%;
  --foreground: 0 0% 98%;
  /**  ... **/
}

最後に

あくまで環境を整えた段階なので今後このアプローチで無理や不整合が生じる可能性はありますが、CSS変数名やプレフィックスが被らない限り、理論的には既存スタイルへの影響はないので少なくとも事故を起こさず安全かつ段階的に Tailwind CSS に移行できると期待してます。

既存プロダクトを Tailwind CSS (や shadcn/ui)に移行したいけど既存スタイルが幅を利かせていて諦めている人はぜひこのアプローチでトライしてみてください。

Discussion