React에서 Tailwind 클래스 재정의

8453 단어 tailwindcsscssreact

EDIT: A previous version of this article mentioned tailwind-override, but this package has been replaced with a more complete library that merges more Tailwind classes.



문제



Tailwind CSS를 사용하여 미리 스타일이 지정된 파란색 버튼을 표시하고 더 많은 클래스를 추가하여 사용자 정의할 수 있는 간단한 React 구성 요소를 만든다고 상상해 보십시오.

function Button({ label, className, ...props }) {
  const classes = `
    border
    border-black
    bg-blue-600
    p-4
    rounded-lg
    text-white
    text-xl
    ${className ?? ""}
  `;
  return <button className={classes}>{label}</button>;
}


다음과 같이 사용할 수 있습니다.

<Button label="Hello" />


기본 파란색 버튼 스타일 지정

그리고 그것은 광고된 대로 작동합니다. 이제 색상을 빨간색으로 변경하려고 합니다.

<Button label="Hello" className="bg-red-600"/>


맞춤형 빨간색 버튼... 잠깐!?

방금 무슨 일이 일어났나요? 새 CSS 클래스를 className 에 추가했으므로 렌더링된 HTML에 실제로 포함되어 있는지 확인해 보겠습니다.

<button class="
    border
    border-black
    bg-blue-600
    p-4
    rounded-lg
    text-white
    text-xl
    bg-red-600
  ">Hello</button>


바로 끝에 bg-red-600 가 있고 bg-blue-600 뒤에 옵니다. 클래스는 이전에 온 모든 것을 재정의해야 합니다. 맞습니까?

잘못된.

원인


class HTML 속성이 허용하는 공백으로 구분된 CSS 클래스 목록은 브라우저에서 CSS 규칙 우선 순위를 계산할 때 목록으로 처리되지 않는 것으로 나타났습니다. class 특성에는 실제로 요소가 가진 클래스 세트가 포함되어 있으므로 순서는 중요하지 않습니다.

이 문제는 Tailwind에만 국한되지 않습니다. 동일한 CSS 속성을 설정하는 두 개의 CSS 클래스에서 발생할 수 있습니다. 다음과 같이 간단할 수 있습니다.

<!DOCTYPE html>
<html>
  <head>
    <style>
      .red {
        color: red;
      }

      .blue {
        color: blue;
      }
    </style>
  </head>
  <body>
    <p class="blue red">Sample red text... not!</p>
  </body>
</html>


.blue 규칙이 .red 규칙보다 우선합니다.

클래스가 class 속성에 나타나는 순서는 중요하지 않으므로 CSS 스타일시트에서 나중에 오는 규칙이 우선합니다.

다시 Tailwind로 돌아와서 우연히 Tailwind 스타일시트 파일이 .bg-blue-600 다음에 .bg-red-600 규칙을 정의하면 bg-blue-600가 매번 승리합니다.

해결책



비 순풍



경우에 따라 스타일시트와 요소에 적용된 규칙specificity을 변경하여 이 문제를 해결할 수 있습니다. 다음 규칙은 모두 원래.red 규칙보다 우선 순위가 높습니다(원래.blue 규칙보다 우선).

p.red
.red.blue
#special
body .red


확인할 가치가 있는 neat specificity calculator이 있습니다.

순풍



이제 위의 솔루션은 Tailwind에서 작동하지 않습니다. 그 개념 자체가 스타일시트를 변경하지 않고 사용할 수 있는 유틸리티 클래스를 갖는 것이기 때문입니다.

자신의 클래스 다음에 어떤 클래스가 나타날지 모르는 경우 충돌을 감지하고 마지막 항목을 제외한 모든 항목을 제거하는 방법이 필요합니다. 이것이 바로 tailwind-merge npm 패키지가 하는 일입니다.

다음과 같이 사용할 수 있습니다.

import { twMerge } from "tailwind-merge";

function Button({ label, className, ...props }) {
  const classes = twMerge(`
    border
    border-black
    bg-blue-600
    p-4
    rounded-lg
    text-white
    text-xl
    ${className ?? ""}
  `);
  return <button className={classes}>{label}</button>;
}


올바른 색상의 버튼

그리고 렌더링된 HTML에 더 이상 bg-blue-600가 포함되어 있지 않음을 확인할 수 있습니다.

<button class=" border border-black p-4 rounded-lg text-white text-xl bg-red-600 ">Hello</button>


결론


class HTML 속성에서 CSS 클래스 이름의 순서는 중요하지 않기 때문에 요소의 기존 클래스를 재정의하는 유일한 방법은 새 클래스와 충돌하는 이전 클래스를 모두 제거하는 것입니다.

어떻게 생각해? 이전에 이 문제에 직면한 적이 있습니까? 새 클래스보다 먼저 나오는 Tailwind 클래스를 재정의하는 더 좋은 방법을 알고 있나요?

좋은 웹페이지 즐겨찾기