1. Intro

Tailwind CSS는 유틸리티 중심의 CSS 프레임워크로, 간단하고 반복적인 클래스 이름을 사용하여 스타일을 적용합니다. 그러나, 때때로 동일한 종류의 여러 클래스를 동시에 적용할 때 문제가 발생할 수 있습니다. 예를 들어, text-smtext-20 같은 서로 다른 폰트 사이즈 클래스를 동시에 적용하려 할 때, 이러한 충돌을 관리하는 것이 필요합니다.

2. tailwind-merge의 한계

tailwind-merge 라이브러리는 이러한 클래스 충돌을 해결하기 위해 만들어졌지만, 맞춤형 클래스에 대해서는 완벽하지 않습니다. 이 라이브러리는 Tailwind의 기본 클래스들 간의 충돌을 잘 관리하지만, 사용자 정의 클래스에 대해서는 기대한 대로 작동하지 않을 수 있습니다. 이는 사용자 정의 클래스가 Tailwind의 내부 로직과 충돌할 때 발생합니다.

twMerge 예시

<>
  <div className={twMerge('text-sm', 'text-h1')}>TEST</div>
  <div className="text-h1">h1</div>
</>

Screenshot 2023-11-21 at 3.12.27 PM.png

사진처럼 두 개의 옵션이 모두 class에 들어가며,

Screenshot 2023-11-21 at 3.12.01 PM.png

실제 적용은 앞의 속성인 text-sm만 적용되는 것을 확인할 수 있습니다.

3. 해결 방안

이 문제를 해결하기 위해, extendTailwindMerge 함수를 사용하여 커스텀 cn 함수를 만들었습니다. 이 함수는 사용자 정의 클래스와 Tailwind 클래스 간의 충돌을 해결하는 데 중점을 둡니다. 특히, **fontSizes**와 같은 맞춤형 스타일 설정을 포함하여, Tailwind의 기본 설정을 확장하고, 클래스 충돌을 효과적으로 관리합니다.

// src/utils/cn.ts
import { fontSizes } from '@/style/theme';
import { clsx } from 'clsx';
import { extendTailwindMerge } from 'tailwind-merge';

import type { ClassValue } from 'clsx';

const customTwMerge = extendTailwindMerge({
  classGroups: {
    'font-size': [
      {
        text: Object.keys(fontSizes),
      },
    ],
  },
});

const cn = (...inputs: ClassValue[]) => {
  return customTwMerge(clsx(inputs));
};

export default cn;

코드

<>
  <div className={cn('text-sm', 'text-h1')}>TEST</div>
  <div className="text-h1">h1</div>
</>

커스텀한 cn유틸함수를 적용하면 아래 사진처럼 뒤에 오는 text-h1만 남아있는 것을 확인할 수 있습니다.

Screenshot 2023-11-21 at 3.16.46 PM.png

Screenshot 2023-11-21 at 3.16.53 PM.png