🎐

tailwind-mergeで意図しないクラスがマージされる現象を回避する

2023/10/01に公開

結論

classGroupsでグループを指定する。

const twMerge = extendTailwindMerge({
  classGroups: {
    'font-size': ['作成したカスタムクラス'],
  }
})

tailwind-mergeとは

Utility function to efficiently merge Tailwind CSS classes in JS without style conflicts.
スタイルの競合なく、JSでTailwind CSSクラスを効率的にマージするためのユーティリティ関数。

https://github.com/dcastil/tailwind-merge
最近ではtailwind-variantsshadcn/uiでも利用されています。

マージ例:

twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hover:bg-dark-red p-3 bg-[#B91C1C]'

カスタムクラス問題 font-sizeの例

通常tailwindcssで用意されているクラスを使用する場合、基本的に問題は発生しませんが
同じグループに属しているが異なるCSSプロパティを使用するクラス、かつカスタムクラスで独自に作成したクラスなどでは意図しないマージが行われる場合があります。
text-lg(font-size)、text-bulue-500(color)などのtext-***系では特に問題が発生しがちです。

カスタムクラスでfont-sizeクラスを追加

module.exports = {
  theme: {
    extend: {
      fontSize: {
        'body': ['1rem',
          {
            lineHeight: '1.5',
            fontWeight: '400',
          }
	]
}}}}

上記のカスタムクラスではtext-bodyでfont-size、line-heightなどが設定されたスタイルが使用できるようになりますが、color設定はありません。
このクラスをcolor指定と同時に使用すると、プロパティの被りはないにも関わらずマージが行われ、text-bodyは消えてしまいます。

twMerge('text-body', 'text-blue-500')
// → 'text-blue-500' ※text-bodyが消えfont-sizeやline-heighの指定が消えてしまう

twMerge('text-body', 'text-lg')
// → 'text-body text-lg' ※font-size指定で競合が発生する

これはtailwind-mergeが行うfont-size系の処理ではtext-以降の文字列部分が未知の色クラスという判定になるため、text-bodytext-blue-500で競合が発生したと見なされtext-blue-500だけが残る結果となります。

このような意図しないマージを回避するためにtailwind-mergeではclass-groupsというオプションが用意されています。

class-groupsオプション

https://github.com/dcastil/tailwind-merge/blob/v1.14.0/docs/configuration.md#class-groups

今回はtext-bodybody部分が色ではなく、font-sizeのグループに属する文字列ということをtailwind-merge側に伝える必要があるため、以下のようなclass-groupsオプションの指定を行います。

const twMerge = extendTailwindMerge({
  classGroups: {
    'font-size': ['text-body'],
  }
})

こちらの指定を行うことでtext-bodytexe-blue-500が同居できるようになります。

twMerge('text-body', 'text-blue-500')
// → 'text-body text-blue-500'

twMerge('text-body', 'text-lg')
// → 'text-lg'

※font-sizeのグループはソースの以下部分で確認できます。
https://github.com/dcastil/tailwind-merge/blob/v1.14.0/src/lib/default-config.ts#L619

Discussion