🤖

Tailwind v4にアップデートしてみた感想 ──figmaトークンとの連携設定編

に公開

ご覧いただきありがとうございます!PeopleX社でフロントエンドエンジニアをしているせりせりです。前回こちらの記事でfigma上で定義されたトークンを効率的にコードに反映させる手法についてご紹介させていただきました。上記の記事では

  • figmaトークン→style-dictionaryによって中間ファイルを生成→tailwind.config.jsに反映

という一連の流れにより、コマンド一つでTailwindのトークンをコードに反映する方法について紹介しました。しかしstyle-dictionaryによって生成される中間ファイルが多く、その中間ファイルをさらに、tailwind.config.jsに反映させる必要がある部分が冗長だなーと思っていました。

その問題に対して、Tailwind v3をv4にすることで、その過程を大幅に省略し改善できるんじゃないか、と思いトライしてみたのですが、意外と直感的になった部分ばかりでもなかったため、何が突っかかっているのかこの記事の中で備忘録的に書かせていただきます。

Tailwind v3 →v4 は何が変わったのか?

Tailwind v4では、設定やビルドまわりが大幅に刷新されました。特に大きな変化は以下の3点です。

  • 設定ファイル不要化:tailwind.config.jsが必須ではなくなり、CSS内で直接@themeディレクティブを使ってテーマ定義が可能になった。

  • ネイティブCSS変数対応:トークンやカラーパレットなどがCSS変数ベースで管理できるようになった。

  • パフォーマンスとDXの向上:内部構造の見直しによりビルドが高速化。PostCSS設定も不要になり、導入がシンプルになった。

この変更により、style-dictionaryで生成が必要な中間ファイルの数が減り、Figmaトークンをより直感的にTailwindに反映できるようになりました(と思っていました)。

💡補足:v4でも tailwind.config.js は引き続き利用可能

「設定ファイル不要化」とはいえ、Tailwind v4ではtailwind.config.jsが完全に廃止されたわけではありません。これまで通り設定ファイルを置くことで、themeの拡張やplugins、content指定などを従来の方法で管理できます。

どのようなフローでfigmaトークンをtailwindに反映しているか

詳細はこちらの記事に記述していますが、弊チームでは大まかな流れとして以下のような手順でfigmaトークンとTailwindクラスを連携しています。

  1. figmaトークンをDesign Tokens Managerなどのプラグインを使いJSON形式でexport
  2. style-dictionaryで上述のトークンを別のJSONや、typographyのutilityクラスに変換
  3. tailwind.config.jsに上述のJSONやutilityクラスを取り込む

Tailwind v3 ではtailwind.config.js経由でしかTailwindへのトークンの反映ができません。しかしv4にアップデートするとcssから直接Tailwindクラスが定義することができるようになるため、3の設定が必要なくなります。

Tailwind v4では@themeのカスタムディレクティブを指定し、例えば、以下のような予約語のprefixをつけることで直接CSSをTailwindクラスにマッピングすることができます。

この例では例えば以下のようなcssを定義すれば、bg-red-300のように背景色を使うこともできるし、text-red-300のようにし、文字色としても使用できることを意味します。

@theme{
  --color-red-300: #d75768;
}

詳しくはこちら

同様のことを再現するために、Tailwind v3 まででは、

const config: Config = {
  ...
  theme: {
    extend: {
      colors: {
        ...
        red: {
          ...,
          '300': '#d75768',
          ...
        }
      ...
    }
    ...
  }

のようなtailwind.config.jsでの設定が必要だったため、これだけを見るとかなり楽になる印象を受けます。

実際にやってみた感想

実際にやってみてですが、必要なファイル数が減った一方で、想像以上に予約語に合わせたcssの変数名を定義することが直感的でなく思いました。
例えば、我々のfigmaでのデザイントークンからexportされるJSONは以下のようなものです。

{
  "token": {
    "red": {
      "300": {
        "$type": "color",
        "$value": "#d75768"
      },
      ...
    }
  }
}

これを css/variablesのようなstyle-dictionaryで用意されているフォーマッターを使用して生成すると以下のようなcssの変数名で生成されます(JSONの階層順、tokenred300に沿って命名される)。

--token-red-300: #d75768

これではTailwindのクラスに反映されないため、custom formatterを定義し、

--color-red-300: #d75768

のようなcssとして生成する必要があります。

上記のような変数名として生成するには、以下のようなcustom formatterstyle-dictionary使用時に定義する必要があります。

scripts/registerFormatter.js
import StyleDictionary from 'style-dictionary';

StyleDictionary.registerFormat({
  name: 'tailwind-theme-css',
  formatter: function({ dictionary }) {
    const cssVariables = dictionary.allProperties
      .filter((prop) => prop.attributes.category === 'color')
      .map((prop) => {
        // e.g. ['token', 'red', '300'] → '--color-red-300'
        const variableName = prop.path.slice(1).join('-'); 
        return `  --color-${variableName}: ${prop.value};`;
      })
      .join('\n');

    return `@theme {\n${cssVariables}\n}`;
  },
});

こうすることでtokenred300のような順でJSONで定義されている変数も--color-red-300のような変数名として出力することができ、Tailwind変数に反映することができます。

しかし、こちらわかりやすいでしょうか???上の例だけだったらまだ良いのですが、上記のようなstringの置き換えをradiusshadowなど、Tailwindで定義したい他のクラスでも同様に行う必要があります。

tailwind.config.jsへの取り込みが必要なくなったというメリットはありますが、個人的には多少冗長とはいえ、tailwind.config.jsを通してJSONで管理するやり方の方が、直感的だったなーなどと思っているところです。

まとめ

Tailwind v4では、CSSファーストの設定が取り入れられ、tailwind.config.jsなどの設定ファイルが必要なくなりました。これにより、

  • configファイルを通さずにカスタマイズできる
  • ビルド速度の改善
  • CSS変数を使った動的テーマの切り替えが容易になる

といった改善がされました。

一方で冗長性を排除することにより、一連のフローの直感性が上がることを期待していましたが、JSONで定義されるconfigファイルを中継しての方が管理のしやすさであったり、configファイルを一目で見た際により明示的にどんなクラスが定義されているかわかりやすい印象を受けました。

最終的には、「どのレイヤーで抽象化や自動化を行うか」という設計判断の話に行き着くのだと思います。CSS ファーストで柔軟性を高める方向性は間違いなくモダンで、チームやプロジェクトによっては非常にマッチすると思います。一方で、弊チームのように

  • Figma → Style Dictionary → Tailwind

というデザインシステム連携を重視しているケースでは、中間の JSON(=プレーンテキスト)による構造的・機械可読な管理が依然として強みを発揮します。

「プレーンテキストに勝るものはない(Plain text wins)」

という、昔からエンジニアリング界隈で言われている思想そのものでした。

Tailwind v4 による “CSS ファースト” のアプローチは確かにエレガントですが、チーム開発やトークン管理のような「複数の抽象レイヤーを横断する設計」では、人にも機械にも読みやすいプレーンテキスト(JSON)をハブにすることで、構造的な一貫性と透明性を保ちやすいと感じました。

PeopleXテックブログ

Discussion