tailwind-merge の使い方

Merge Tailwind CSS classes without style conflicts

v3.5.0/週MITユーティリティ
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

tailwind-merge の使い方 — Tailwind CSSのクラス競合を解決するユーティリティ

一言でいうと

tailwind-merge は、Tailwind CSS のクラス名をマージする際に発生するスタイルの競合を自動的に解決するライブラリです。後から指定したクラスが優先されるように、重複するユーティリティクラスをインテリジェントに除去してくれます。

どんな時に使う?

  1. コンポーネントのスタイルをpropsで上書きしたい時 — ベースのクラスを持つ共通コンポーネントに、呼び出し側からカスタムクラスを渡してスタイルを上書きするケース
  2. 条件分岐でクラスを動的に切り替えたい時 — 状態に応じて px-4px-6 に変えたいが、単純な文字列結合だと両方が残ってしまうケース
  3. clsx / classnames と組み合わせて堅牢なクラス管理をしたい時 — 条件付きクラスの結合と競合解決を同時に行いたいケース

インストール

# npm
npm install tailwind-merge

# yarn
yarn add tailwind-merge

# pnpm
pnpm add tailwind-merge

基本的な使い方

import { twMerge } from 'tailwind-merge';

// 単純な文字列結合だと "px-4 py-2 px-6" となり、どちらが適用されるか不定
// twMerge を使うと後勝ちで競合を解決してくれる
const className = twMerge('px-4 py-2 bg-blue-500', 'px-6 bg-red-500');
// => "py-2 px-6 bg-red-500"

Reactコンポーネントでの典型的な使用例:

import { twMerge } from 'tailwind-merge';
import { type ComponentProps } from 'react';

type ButtonProps = ComponentProps<'button'> & {
  variant?: 'primary' | 'secondary';
};

function Button({ variant = 'primary', className, children, ...props }: ButtonProps) {
  const baseClasses = 'rounded-md px-4 py-2 font-semibold text-white';
  const variantClasses = {
    primary: 'bg-blue-600 hover:bg-blue-700',
    secondary: 'bg-gray-600 hover:bg-gray-700',
  };

  return (
    <button
      className={twMerge(baseClasses, variantClasses[variant], className)}
      {...props}
    >
      {children}
    </button>
  );
}

// 使用側:px-4 が px-8 に上書きされる
<Button className="px-8">Wide Button</Button>
// => "rounded-md py-2 font-semibold text-white bg-blue-600 hover:bg-blue-700 px-8"

よく使うAPI

1. twMerge — 基本のマージ関数

最も頻繁に使う関数です。複数の文字列を受け取り、競合を解決した1つのクラス文字列を返します。

import { twMerge } from 'tailwind-merge';

twMerge('text-red-500 text-lg', 'text-blue-500');
// => "text-lg text-blue-500"

// undefined, null, false も安全に渡せる
twMerge('p-4', undefined, null, false, 'p-6');
// => "p-6"

// 配列も受け取れる
twMerge(['flex items-center', 'gap-4']);
// => "flex items-center gap-4"

2. twJoin — 競合解決なしの高速結合

競合解決が不要で、単にクラス名を安全に結合したいだけの場合に使います。twMerge より高速です。

import { twJoin } from 'tailwind-merge';

twJoin('flex', 'items-center', undefined, 'gap-4');
// => "flex items-center gap-4"

// 競合解決はしない(両方残る)
twJoin('px-4', 'px-6');
// => "px-4 px-6"

3. extendTailwindMerge — カスタム設定でマージ関数を生成

カスタムのTailwind設定(独自ユーティリティやカスタムテーマ値)がある場合に使います。

import { extendTailwindMerge } from 'tailwind-merge';

const twMerge = extendTailwindMerge({
  extend: {
    classGroups: {
      // カスタムフォントサイズを追加
      'font-size': [{ text: ['tiny', 'huge'] }],
    },
  },
});

twMerge('text-tiny', 'text-lg');
// => "text-lg"(text-tiny がカスタム値として認識され、競合解決される)

4. createTailwindMerge — 完全カスタムのマージ関数を生成

デフォルト設定を使わず、ゼロから設定を構築したい場合に使います。バンドルサイズを最小化したい上級者向けです。

import { createTailwindMerge, getDefaultConfig } from 'tailwind-merge';

const twMerge = createTailwindMerge(getDefaultConfig);

twMerge('bg-red-500', 'bg-blue-500');
// => "bg-blue-500"

5. fromTheme — テーマ値の参照ヘルパー

extendTailwindMerge 内でテーマのスケール値を参照するためのヘルパーです。

import { extendTailwindMerge, fromTheme } from 'tailwind-merge';

const twMerge = extendTailwindMerge({
  extend: {
    classGroups: {
      // カスタムユーティリティに既存のspacingスケールを適用
      'custom-spacing': [{ 'custom-space': [fromTheme('spacing')] }],
    },
  },
});

twMerge('custom-space-4', 'custom-space-8');
// => "custom-space-8"

類似パッケージとの比較

特徴tailwind-mergeclsx / classnamescn (自作ヘルパー)
クラス文字列の結合
Tailwindクラスの競合解決twMerge + clsx で実現
条件付きクラス指定△(基本的な falsy 除去のみ)✅(オブジェクト記法対応)
バンドルサイズ~6kB (gzip)~0.5kB (gzip)組み合わせ次第
Tailwind設定のカスタマイズ

実務でよく見るパターン: clsxtailwind-merge を組み合わせた cn ヘルパーを作るのが定番です。

// lib/utils.ts — 多くのプロジェクトで採用されているパターン
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
// 使用例
import { cn } from '@/lib/utils';

cn('px-4 py-2', isActive && 'bg-blue-500', { 'opacity-50': isDisabled });

注意点・Tips

1. パフォーマンスに関して

tailwind-merge は内部でLRUキャッシュを持っています。同じ入力に対する結果はキャッシュされるため、再レンダリング時のパフォーマンスは良好です。ただし、初回呼び出しは文字列解析のコストがあるため、レンダリングに関係ない場所(例:サーバーサイドのバッチ処理)で大量に呼ぶ場合は注意してください。

2. Tailwind CSS v4 対応

tailwind-merge v3 系は Tailwind CSS v4 に対応しています。v3 系の Tailwind CSS を使っている場合は tailwind-merge v2 系を使用してください。

※ バージョン対応は変更される可能性があります。公式リポジトリで最新の互換性情報を確認してください。

3. カスタムクラスは認識されない

tailwind-merge は Tailwind CSS の標準ユーティリティクラスのみを認識します。独自のユーティリティやプラグインで追加したクラスは、extendTailwindMerge で設定しない限り競合解決の対象になりません。

// ❌ カスタムクラスは競合解決されない
twMerge('custom-padding-sm', 'custom-padding-lg');
// => "custom-padding-sm custom-padding-lg"(両方残る)

// ✅ extendTailwindMerge で登録すれば解決される

4. 修飾子(レスポンシブ・状態)も正しく処理される

twMerge('hover:bg-red-500 md:px-4', 'hover:bg-blue-500 md:px-6');
// => "hover:bg-blue-500 md:px-6"

同じ修飾子プレフィックスを持つクラス同士でのみ競合解決が行われます。hover:bg-red-500bg-blue-500 は別グループとして扱われ、両方残ります。

5. important修飾子やarbitrary valuesにも対応

twMerge('!px-4', '!px-6');
// => "!px-6"

twMerge('bg-[#123456]', 'bg-[#654321]');
// => "bg-[#654321]"

まとめ

tailwind-merge は、Tailwind CSS ベースのコンポーネント設計において「クラスの上書き」を安全に行うための必須ライブラリです。特に clsx と組み合わせた cn ヘルパーパターンは、shadcn/ui をはじめ多くのプロジェクトで標準的に採用されています。Tailwind CSS でコンポーネントライブラリを構築するなら、まず導入を検討すべきパッケージです。