개요

플러그인을 사용하면 CSS 대신 JavaScript를 통해 Tailwind가 사용자의 스타일시트에 주입할 새로운 스타일을 등록할 수 있습니다.

첫 번째 플러그인을 시작하려면, tailwindcss/plugin에서 Tailwind의 plugin 함수를 가져옵니다. 그런 다음 plugins 배열 안에서, 가져온 plugin 함수를 첫 번째 인자로 익명 함수와 함께 호출합니다.

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, e, config }) {
      // 여기에 커스텀 스타일을 추가하세요
    }),
  ]
}

플러그인 함수는 단일 객체 인자를 받으며, 이 객체는 여러 헬퍼 함수로 구조 분해할 수 있습니다:

  • addUtilities(): 새로운 정적 유틸리티 스타일을 등록
  • matchUtilities(): 새로운 동적 유틸리티 스타일을 등록
  • addComponents(): 새로운 정적 컴포넌트 스타일을 등록
  • matchComponents(): 새로운 동적 컴포넌트 스타일을 등록
  • addBase(): 새로운 기본 스타일을 등록
  • addVariant(): 커스텀 정적 변형을 등록
  • matchVariant(): 커스텀 동적 변형을 등록
  • theme(): 사용자의 테마 설정에서 값을 조회
  • config(): 사용자의 Tailwind 설정에서 값을 조회
  • corePlugins(): 코어 플러그인이 활성화되었는지 확인
  • e(): 클래스 이름으로 사용될 문자열을 수동으로 이스케이프

공식 플러그인

우리는 여러 가지 이유로 코어에 포함되지 않은 인기 있는 기능들을 위한 몇 가지 공식 플러그인을 개발했습니다.

플러그인은 npm을 통해 설치한 후 tailwind.config.js 파일에 추가하여 프로젝트에 적용할 수 있습니다.

tailwindconfig.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // ...
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/container-queries'),
  ]
}

타이포그래피

@tailwindcss/typography 플러그인은 마크다운이나 CMS 데이터베이스와 같은 소스에서 가져온 콘텐츠 블록에 적절한 타이포그래피 스타일을 빠르게 적용할 수 있는 prose 클래스 세트를 제공합니다.

<article class="prose lg:prose-xl">
  <h1>치즈가 든 갈릭 브레드: 과학이 말해주는 것</h1>
  <p>
    수년 동안 부모들은 치즈가 든 갈릭 브레드의 건강상 이점을 아이들에게 강조해 왔으며, 이 음식은 우리 문화에서 아이들이 할로윈에 따뜻하고 치즈가 든 빵으로 분장할 정도로 상징적인 지위를 얻었습니다.
  </p>
  <p>
    하지만 최근 연구에 따르면 이 유명한 전채 요리가 전국적으로 발생하는 광견병 사례와 관련이 있을 수 있다고 합니다.
  </p>
  <!-- ... -->
</article>

타이포그래피 플러그인에 대해 더 알아보기 →

@tailwindcss/forms 플러그인은 폼 엘리먼트를 유틸리티 클래스로 쉽게 스타일링할 수 있도록 도와주는 폼 리셋 레이어를 추가합니다.

<!-- select 엘리먼트의 패딩을 커스터마이징할 수 있습니다: -->
<select class="px-4 py-3 rounded-full">
  <!-- ... -->
</select>

<!-- 또는 텍스트 색상 유틸리티를 사용해 체크박스 색상을 변경할 수 있습니다: -->
<input type="checkbox" class="rounded text-pink-500" />

폼 플러그인에 대해 더 알아보기 →

가로세로 비율(Aspect Ratio)

@tailwindcss/aspect-ratio 플러그인은 오래된 브라우저에서도 작동하는 네이티브 aspect-ratio 대안입니다. 이 플러그인은 aspect-w-*aspect-h-* 클래스를 추가하여 엘리먼트에 고정된 가로세로 비율을 지정할 수 있게 해줍니다.

<div class="aspect-w-16 aspect-h-9">
  <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

가로세로 비율 플러그인에 대해 더 알아보기 →

컨테이너 쿼리

@tailwindcss/container-queries 플러그인은 뷰포트 대신 @container로 표시된 부모 요소의 크기에 따라 스타일을 적용할 수 있는 @{size} 변형(예: @sm, @md)을 추가합니다.

<div class="@container">
  <div class="@lg:text-sky-400">
    <!-- ... -->
  </div>
</div>

컨테이너 쿼리 플러그인에 대해 더 알아보기 →


유틸리티 추가하기

addUtilitiesmatchUtilities 함수를 사용하면 Tailwind의 utilities 레이어에 새로운 스타일을 등록할 수 있습니다.

Tailwind에 기본으로 포함된 유틸리티와 마찬가지로, 플러그인을 통해 추가된 유틸리티도 프로젝트에서 실제로 사용될 때만 생성된 CSS에 포함됩니다.

정적 유틸리티

사용자가 제공한 값을 지원하지 않는 간단한 정적 유틸리티를 등록하려면 addUtilities 함수를 사용하세요:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.content-auto': {
          'content-visibility': 'auto',
        },
        '.content-hidden': {
          'content-visibility': 'hidden',
        },
        '.content-visible': {
          'content-visibility': 'visible',
        },
      })
    })
  ]
}

스타일을 자바스크립트로 표현하는 방법에 대해 더 알아보려면 CSS-in-JS 문법 참고 문서를 확인하세요.

동적 유틸리티

matchUtilities 함수를 사용하여 사용자의 theme 설정에 정의된 값에 매핑되는 유틸리티를 등록할 수 있습니다:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  },
  plugins: [
    plugin(function({ matchUtilities, theme }) {
      matchUtilities(
        {
          tab: (value) => ({
            tabSize: value
          }),
        },
        { values: theme('tabSize') }
      )
    })
  ]
}

이렇게 정의된 유틸리티는 임의 값도 지원합니다. 따라서 테마에 없는 값을 대괄호 표기법을 사용하여 적용할 수 있습니다:

<div class="tab-[13]">
  <!-- ... -->
</div>

접두사와 important 설정

기본적으로 플러그인 유틸리티는 사용자의 prefiximportant 설정을 자동으로 따릅니다.

예를 들어, 다음과 같은 Tailwind 설정이 있다고 가정해 보겠습니다:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
  important: true,
  // ...
}

위의 예제 플러그인은 다음과 같은 CSS를 생성합니다:

.tw-content-auto {
  content-visibility: auto !important;
}
.tw-content-hidden {
  content-visibility: hidden !important;
}
.tw-content-visible {
  content-visibility: visible !important;
}

수식어와 함께 사용하기

addUtilities를 사용해 추가한 커스텀 유틸리티는 자동으로 수식어와 함께 사용할 수 있습니다:

<div class="content-auto lg:content-visible">
  <!-- ... -->
</div>

더 자세한 내용은 호버, 포커스 및 기타 상태 문서에서 확인할 수 있습니다.

기본값 제공하기

유틸리티 플러그인은 plugin 함수의 두 번째 인자로 설정 객체를 포함하여 기본값을 제공할 수 있습니다:

./plugins/tab-size.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin(function({ matchUtilities, theme }) {
  matchUtilities(
    {
      tab: (value) => ({
        tabSize: value
      }),
    },
    { values: theme('tabSize') }
  )
}, {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  }
})

이 값들은 기본 설정에 있는 값들과 동일하게 동작하며, 최종 사용자가 이를 재정의하거나 확장할 수 있습니다.

컴포넌트 추가하기

addComponents 함수를 사용하면 Tailwind의 components 레이어에 새로운 스타일을 등록할 수 있습니다.

이 기능은 버튼, 폼 컨트롤, 알림 등과 같이 다른 프레임워크에서 자주 볼 수 있는 미리 만들어진 컴포넌트 스타일을 추가할 때 유용합니다. 이러한 스타일은 유틸리티 클래스로 재정의해야 할 수도 있습니다.

플러그인에서 새로운 컴포넌트 스타일을 추가하려면, CSS-in-JS 문법을 사용하여 스타일을 전달하면서 addComponents를 호출합니다:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      addComponents({
        '.btn': {
          padding: '.5rem 1rem',
          borderRadius: '.25rem',
          fontWeight: '600',
        },
        '.btn-blue': {
          backgroundColor: '#3490dc',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#2779bd'
          },
        },
        '.btn-red': {
          backgroundColor: '#e3342f',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#cc1f1a'
          },
        },
      })
    })
  ]
}

Tailwind의 다른 컴포넌트 클래스와 마찬가지로, 플러그인을 통해 추가된 컴포넌트 클래스는 프로젝트에서 실제로 사용될 때만 생성된 CSS에 포함됩니다.

Prefix와 important_Bm7MuFNTyHRTDmwCSEFg4q

기본적으로 컴포넌트 클래스는 사용자의 prefix 설정을 자동으로 따르지만, 사용자의 important 설정에는 영향을 받지 않습니다.

즉, 다음과 같은 Tailwind 설정이 주어졌을 때:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
  important: true,
  // ...
}

위의 예제 플러그인은 다음과 같은 CSS를 생성합니다:

.tw-btn {
  padding: .5rem 1rem;
  border-radius: .25rem;
  font-weight: 600;
}
.tw-btn-blue {
  background-color: #3490dc;
  color: #fff;
}
.tw-btn-blue:hover {
  background-color: #2779bd;
}
.tw-btn-red {
  background-color: #e3342f;
  color: #fff;
}
.tw-btn-red:hover {
  background-color: #cc1f1a;
}

컴포넌트 선언을 important로 만드는 것은 드물지만, 정말로 필요하다면 수동으로 !important를 추가할 수 있습니다:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      addComponents({
        '.btn': {
          padding: '.5rem 1rem !important',
          borderRadius: '.25rem !important',
          fontWeight: '600 !important',
        },
        // ...
      })
    })
  ]
}

기본적으로 선택자 내의 모든 클래스에는 접두사가 붙습니다. 따라서 다음과 같이 더 복잡한 스타일을 추가하면:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  prefix: 'tw-',
  plugins: [
    plugin(function({ addComponents }) {
      const components = {
        // ...
        '.navbar-inverse a.nav-link': {
            color: '#fff',
        }
      }

      addComponents(components)
    })
  ]
}

다음과 같은 CSS가 생성됩니다:

.tw-navbar-inverse a.tw-nav-link {
    color: #fff;
}

modifiers_ifKPvTE8bYug4bAM67NFC7와 함께 사용하기

addComponents를 사용해 추가한 모든 컴포넌트 클래스는 자동으로 수정자(modifiers)와 함께 사용할 수 있습니다:

<div class="btn md:btn-lg">
  <!-- ... -->
</div>

더 자세한 내용은 Hover, Focus, and Other States 문서에서 확인할 수 있습니다.


기본 스타일 추가하기

addBase 함수를 사용하면 Tailwind의 base 레이어에 새로운 스타일을 등록할 수 있습니다. 이 함수를 사용해 기본 타이포그래피 스타일, 전역 리셋 스타일, 또는 @font-face 규칙 등을 추가할 수 있습니다.

플러그인에서 새로운 기본 스타일을 추가하려면, CSS-in-JS 문법을 사용해 스타일을 전달하면서 addBase를 호출합니다:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addBase, theme }) {
      addBase({
        'h1': { fontSize: theme('fontSize.2xl') },
        'h2': { fontSize: theme('fontSize.xl') },
        'h3': { fontSize: theme('fontSize.lg') },
      })
    })
  ]
}

기본 스타일은 divh1과 같은 순수 선택자를 대상으로 하기 때문에, 사용자가 설정한 prefiximportant 설정을 따르지 않습니다.

변형 추가하기

addVariantmatchVariant 함수를 사용하면 여러분만의 커스텀 수정자를 등록할 수 있습니다. 이 수정자는 hover, focus, supports와 같은 내장 변형과 동일하게 사용할 수 있습니다.

정적 변형

간단한 커스텀 변형을 만들려면 addVariant 함수를 사용하세요. 이 함수는 커스텀 변형의 이름과 선택자가 어떻게 수정되어야 하는지를 나타내는 형식 문자열을 인자로 받습니다.

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('hocus', ['&:hover', '&:focus'])
      addVariant('inverted-colors', '@media (inverted-colors: inverted)')
    })
  ]
}

첫 번째 인자는 사용자가 HTML에서 사용할 수정자 이름입니다. 위 예제를 통해 다음과 같은 클래스를 작성할 수 있습니다.

<form class="flex inverted-colors:outline ...">
  <input class="optional:border-gray-300 ..." />
  <button class="bg-blue-500 hocus:bg-blue-600">...</button>
</form>

동적 변형

내장된 supports-*, data-*, aria-* 변형과 같은 새로운 파라미터화된 변형을 등록하려면 matchVariant 함수를 사용하세요:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ matchVariant }) {
      matchVariant(
        'nth',
        (value) => {
          return `&:nth-child(${value})`;
        },
        {
          values: {
            1: '1',
            2: '2',
            3: '3',
          }
        }
      );
    })
  ]
}

matchVariant로 정의된 변형은 대괄호 표기법을 사용해 임의의 값을 지원합니다:

<div class="nth-[3n+1]:bg-blue-500 ...">
  <!-- ... -->
</div>

같은 변형에서 나온 다른 값들과의 우선순위 문제를 피하기 위해 생성된 CSS의 소스 순서를 제어하려면 sort 옵션을 사용하세요:

matchVariant("min", (value) => `@media (min-width: ${value})`, {
  sort(a, z) {
    return parseInt(a.value) - parseInt(z.value);
  },
});

부모 및 형제 상태

여러분이 만든 커스텀 수식어(modifiers)는 Tailwind의 부모형제 상태 수식어와 자동으로 작동하지 않습니다.

group-*peer-* 버전의 커스텀 수식어를 지원하려면, 특수한 :merge 지시어를 사용하여 별도의 변형(variants)으로 등록해야 합니다. 이렇게 하면 최종 선택자에서 .group.peer 클래스가 한 번만 나타나도록 보장할 수 있습니다.

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('group-optional', ':merge(.group):optional &')
      addVariant('peer-optional', ':merge(.peer):optional ~ &')
    })
  ]
}

설정 확장하기

플러그인은 plugin 함수의 두 번째 인자로 객체를 제공하여 사용자의 tailwind.config.js 설정에 자체 설정 값을 병합할 수 있습니다.

./plugins/tab-size.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin(function({ matchUtilities, theme }) {
  matchUtilities(
    {
      tab: (value) => ({
        tabSize: value
      }),
    },
    { values: theme('tabSize') }
  )
}, {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  }
})

이 방법은 플러그인이 생성하는 클래스에 대한 기본 theme 값을 제공하는 데 유용합니다.

옵션 노출하기

때로는 플러그인이 theme 아래에 속하지 않는 방식으로 구성 가능하도록 만드는 것이 합리적일 수 있습니다. 예를 들어, 사용자가 플러그인이 사용하는 클래스 이름을 커스텀할 수 있도록 하고 싶을 수 있습니다.

이런 경우에는 plugin.withOptions를 사용하여 구성 객체와 함께 호출할 수 있는 플러그인을 정의할 수 있습니다. 이 API는 일반적인 plugin API와 유사하지만, 각 인수는 사용자의 options를 받아들이고 일반 API를 사용하여 전달했을 값을 반환하는 함수여야 합니다:

./plugins/markdown.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin.withOptions(function (options = {}) {
  return function({ addComponents }) {
    const className = options.className ?? 'markdown'

    addComponents({
      [`.${className}`]: {
        // ...
      }
    })
  }
}, function (options) {
  return {
    theme: {
      markdown: {
        // ...
      }
    },
  }
})

사용자는 plugins 설정에서 플러그인을 등록할 때 옵션을 전달하여 플러그인을 호출할 수 있습니다:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('./plugins/markdown.js')({
      className: 'wysiwyg'
    })
  ],
}

사용자는 커스텀 옵션을 전달할 필요가 없는 경우, 이렇게 생성된 플러그인을 일반적으로 등록할 수도 있습니다:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('./plugins/markdown.js')
  ],
}

CSS-in-JS 문법

Tailwind의 플러그인 시스템은 Emotion과 같은 CSS-in-JS 라이브러리에서 사용하는 것과 유사한 문법으로 작성된 CSS 규칙을 JavaScript 객체로 기대합니다. 이는 내부적으로 postcss-js를 통해 동작합니다.

다음은 간단한 CSS 규칙입니다:

.card {
  background-color: #fff;
  border-radius: .25rem;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

이를 CSS-in-JS 객체로 변환하면 다음과 같습니다:

addComponents({
  '.card': {
    'background-color': '#fff',
    'border-radius': '.25rem',
    'box-shadow': '0 2px 4px rgba(0,0,0,0.2)',
  }
})

편의를 위해 속성 이름을 camelCase로 작성할 수도 있으며, 이는 자동으로 dash-case로 변환됩니다:

addComponents({
  '.card': {
    backgroundColor: '#fff',
    borderRadius: '.25rem',
    boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
  }
})

Sass나 Less에서 익숙한 것과 동일한 문법을 사용하여 중첩도 지원됩니다 (postcss-nested를 통해):

addComponents({
  '.card': {
    backgroundColor: '#fff',
    borderRadius: '.25rem',
    boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
    '&:hover': {
      boxShadow: '0 10px 15px rgba(0,0,0,0.2)',
    },
    '@media (min-width: 500px)': {
      borderRadius: '.5rem',
    }
  }
})

동일한 객체 내에서 여러 규칙을 정의할 수도 있습니다:

addComponents({
  '.btn': {
    padding: '.5rem 1rem',
    borderRadius: '.25rem',
    fontWeight: '600',
  },
  '.btn-blue': {
    backgroundColor: '#3490dc',
    color: '#fff',
    '&:hover': {
      backgroundColor: '#2779bd'
    },
  },
  '.btn-red': {
    backgroundColor: '#e3342f',
    color: '#fff',
    '&:hover': {
      backgroundColor: '#cc1f1a'
    },
  },
})

또는 동일한 키를 반복해야 하는 경우 객체 배열로 정의할 수도 있습니다:

addComponents([
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
])