tailwind-mergeで意図しないクラスがマージされる現象を回避する
結論
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クラスを効率的にマージするためのユーティリティ関数。
tailwind-variantsやshadcn/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-body
とtext-blue-500
で競合が発生したと見なされtext-blue-500
だけが残る結果となります。
このような意図しないマージを回避するためにtailwind-mergeではclass-groupsというオプションが用意されています。
class-groupsオプション
今回はtext-body
のbody
部分が色ではなく、font-sizeのグループに属する文字列ということをtailwind-merge側に伝える必要があるため、以下のようなclass-groupsオプションの指定を行います。
const twMerge = extendTailwindMerge({
classGroups: {
'font-size': ['text-body'],
}
})
こちらの指定を行うことでtext-body
とtexe-blue-500
が同居できるようになります。
twMerge('text-body', 'text-blue-500')
// → 'text-body text-blue-500'
twMerge('text-body', 'text-lg')
// → 'text-lg'
※font-sizeのグループはソースの以下部分で確認できます。
Discussion