Tailwind CSS Academy · 강의

플러그인으로 사용자 지정 변형 추가

addVariant로 .is-active와 같은 선택자 또는 data 속성을 대상으로 하는 사용자 지정 상태 변형을 만들고, 마크업에서 클래스 접두사로 사용합니다.

레슨 3/413개 단계

플러그인으로 사용자 지정 변형 추가은(는) CoddyKit의 무료 Tailwind CSS Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Tailwind CSS Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Tailwind CSS Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

What Are Tailwind Variants?

Tailwind variants are the prefixes like hover:, focus:, dark:, and sm: that conditionally apply a utility class. Each variant wraps the generated CSS in a selector or media query. The addVariant plugin helper lets you register your own variant prefixes, enabling you to write things like aria-selected:bg-blue-100, data-active:opacity-100, or is-loading:cursor-wait in your HTML.

The addVariant Helper

addVariant takes two arguments: the variant name (the prefix before the colon) and a selector template string. The selector uses & as a placeholder for the generated class selector. When a user writes hocus:bg-gray-100, Tailwind replaces & with the generated class selector for bg-gray-100 and wraps it in your selector pattern.

const plugin = require('tailwindcss/plugin');

plugin(function({ addVariant }) {
  // 'hocus' = hover OR focus (useful for touch/keyboard parity)
  addVariant('hocus', ['&:hover', '&:focus']);

  // Usage in markup:
  // <button class='hocus:bg-blue-100 hocus:text-blue-700'>
  //   This button highlights on both hover and focus
  // </button>
})

Data Attribute Variants

One of the most practical uses of custom variants is targeting data attributes. Many UI frameworks (like Alpine.js, Headless UI, and Stimulus) communicate state through data-* attributes. Custom variants let you apply Tailwind classes based on these attributes, keeping all styling in the HTML class list rather than mixing CSS with attribute selectors in a stylesheet.

plugin(function({ addVariant }) {
  // Target elements with data-active='true'
  addVariant('data-active', '&[data-active='true']');

  // Target elements with data-state='open'
  addVariant('open', '&[data-state='open']');

  // Target disabled attribute (not just :disabled pseudo-class)
  addVariant('ui-disabled', '&[aria-disabled='true']');
})

// Usage:
// <div data-state='open' class='open:bg-blue-50 open:border-blue-200'>
// <button aria-disabled='true' class='ui-disabled:opacity-50 ui-disabled:cursor-not-allowed'>

Parent State Variants

Tailwind has built-in group and peer patterns, but sometimes you need to target elements based on a parent with a specific class or attribute. Custom variants using the :where() or direct ancestor syntax let you express these relationships. The addVariant selector can reference parent elements by using .parent-class & patterns.

plugin(function({ addVariant }) {
  // Apply when an ancestor has .is-dragging class
  addVariant('dragging', '.is-dragging &');

  // Apply when the form has [data-submitting] attribute
  addVariant('submitting', '[data-submitting] &');

  // Apply when the theme container is in .dark mode
  addVariant('dark-mode', '.dark &');
})

// Usage:
// <form data-submitting>
//   <input class='submitting:opacity-50 submitting:cursor-wait' />
//   <button class='submitting:bg-gray-400 submitting:pointer-events-none'>
//     Submit
//   </button>
// </form>

nth-Child and nth-of-Type Variants

CSS :nth-child() and :nth-of-type() pseudo-selectors enable styling based on position in a list. Tailwind includes odd: and even: variants, but not all :nth-child expressions. Add custom variants for patterns you use repeatedly, like first-three: for the first three list items or last-two: for the last two.

plugin(function({ addVariant }) {
  // First 3 items
  addVariant('first-3', '&:nth-child(-n+3)');

  // Every 3rd item
  addVariant('third', '&:nth-child(3n)');

  // Only child
  addVariant('only', '&:only-child');

  // Not the first child
  addVariant('not-first', '&:not(:first-child)');

  // Not the last child
  addVariant('not-last', '&:not(:last-child)');
})

// Usage:
// <ul>
//   <li class='first-3:font-bold not-last:border-b'>Item 1</li>
//   <li class='first-3:font-bold not-last:border-b'>Item 2</li>
//   <li class='first-3:font-bold not-last:border-b'>Item 3</li>
// </ul>

Combination Variants

The addVariant second argument accepts an array of selectors. When an array is provided, each selector becomes a separate rule, so any selector in the array triggers the variant. This is useful for combination variants that should apply across multiple related selectors — like styling an element when it is either selected or expanded.

plugin(function({ addVariant }) {
  // 'selected' applies on aria-selected OR aria-current
  addVariant('selected', [
    '&[aria-selected='true']',
    '&[aria-current='true']',
    '&[aria-current='page']'
  ]);

  // 'expanded' applies on open disclosure or expanded accordion
  addVariant('expanded', [
    '&[aria-expanded='true']',
    '&[data-state='open']'
  ]);
})

// Usage:
// <a class='selected:bg-blue-50 selected:text-blue-700 expanded:rotate-180'>

Pseudo-Element Variants

You can add variants that target pseudo-elements like ::before, ::after, ::placeholder, and ::selection. The selector template uses &:: for pseudo-elements. Combined with Tailwind's content utilities, pseudo-element variants enable CSS-only decorative elements without extra HTML markup.

plugin(function({ addVariant }) {
  // ::after pseudo-element variant
  addVariant('after', '&::after');

  // ::before pseudo-element variant
  addVariant('before', '&::before');

  // ::selection (text selection styling)
  addVariant('selection', '&::selection');
})

// Usage (combine with content utility for decorative elements):
// <div class="
//   relative
//   after:content-[''] after:absolute after:inset-0
//   after:bg-gradient-to-t after:from-black/50 after:to-transparent
//   after:rounded-xl after:pointer-events-none
// ">

Media Query Variants

Custom variants can also wrap utilities in media queries beyond Tailwind's default breakpoints. Use this for features like prefers-reduced-motion, prefers-contrast, or custom DPI queries. Pass the media query string as the second argument to addVariant with the @media syntax.

plugin(function({ addVariant }) {
  // Prefers reduced motion variant
  addVariant('motion-reduce', '@media (prefers-reduced-motion: reduce)');

  // High contrast mode
  addVariant('contrast-high', '@media (prefers-contrast: high)');

  // Print media
  addVariant('print', '@media print');

  // Pointer: coarse (touch devices)
  addVariant('touch', '@media (pointer: coarse)');
})

// Usage:
// <div class='motion-reduce:transition-none motion-reduce:animate-none'>
// <button class='touch:py-4 touch:text-lg'>Larger on touch</button>

ARIA Attribute Variants for Accessibility

ARIA attributes are the primary way assistive technologies communicate state. Building custom variants for common ARIA states lets you write accessibility-driven styles directly in HTML. Tailwind v3.2+ added some built-in ARIA variants (aria-checked:, aria-selected:), but you can extend this with any ARIA attribute your UI components use.

plugin(function({ addVariant }) {
  // Custom ARIA variants for component states
  addVariant('aria-expanded-true', '&[aria-expanded='true']');
  addVariant('aria-pressed', '&[aria-pressed='true']');
  addVariant('aria-busy', '&[aria-busy='true']');
  addVariant('aria-invalid', '&[aria-invalid='true']');
  addVariant('aria-required', '&[aria-required='true']');
})

// Usage:
// <button aria-pressed='true'
//   class='aria-pressed:bg-blue-600 aria-pressed:text-white
//          aria-busy:opacity-60 aria-busy:cursor-wait'>
//   Toggle
// </button>

Combining addVariant With addUtilities

The most powerful plugins combine addVariant and addUtilities (or addComponents) in a single plugin. For example, a plugin might define a selected: variant AND a set of .menu-item component classes that work together. Packaging related utilities and variants in a single plugin keeps the feature cohesive and easy to enable or disable as a unit.

// A complete 'list-nav' plugin
plugin(function({ addVariant, addComponents }) {
  // Variant: item is the currently active page
  addVariant('nav-active', '&[data-nav-active='true']');

  // Component: base nav item style
  addComponents({
    '.nav-item': {
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      padding: '0.5rem 0.75rem',
      borderRadius: '0.5rem',
      fontSize: '0.875rem',
      fontWeight: '500',
      color: '#4b5563',
      cursor: 'pointer',
      transition: 'background-color 150ms, color 150ms',
      '&:hover': { backgroundColor: '#f3f4f6' }
    }
  });
})
// Usage:
// <a class='nav-item nav-active:bg-blue-50 nav-active:text-blue-700'>

Testing Custom Variants

Verify custom variants work by writing HTML that uses them, running the Tailwind CLI, and inspecting the output CSS. The generated selector should match your addVariant template. Also test that the variant composes correctly with responsive prefixes — md:data-active:bg-blue-100 — and with other state variants like hover:data-active:bg-blue-200. Some variant combinations may produce unexpected selectors; testing confirms the generated CSS is what you expect.

<!-- test.html -->
<div data-active='true'
  class='data-active:bg-blue-50 data-active:border-blue-200
         hover:data-active:bg-blue-100
         md:data-active:bg-blue-200'>
  Content
</div>

<button aria-pressed='true'
  class='aria-pressed:bg-blue-600 aria-pressed:text-white'>
  Toggle
</button>

<!-- Expected generated CSS: -->
/* .data-active\:bg-blue-50[data-active='true'] { background-color: #eff6ff } */
/* @media (min-width: 768px) { .md\:data-active\:bg-blue-200[data-active='true'] { ... } } */

Quick Check

Test your understanding of Tailwind CSS Mastery concepts from this lesson.

Lesson Recap

In this lesson you learned: addVariant creates custom class prefixes that wrap utilities in selector patterns or media queries, data attribute variants let you style based on framework state without writing CSS, and variants can be combined with arrays for multi-selector coverage. Next up we learn how to package and publish Tailwind plugins for reuse across projects.

무료로 시작

AI 튜터와 함께 HTML을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
30
레슨
120

자주 묻는 질문

“플러그인으로 사용자 지정 변형 추가” 강의는 무료인가요?

네 — “플러그인으로 사용자 지정 변형 추가” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Tailwind CSS Academy 강의 전체를 잠금 해제할 수 있습니다. Tailwind CSS Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“플러그인으로 사용자 지정 변형 추가”에서 뭘 배우나요?

addVariant로 .is-active와 같은 선택자 또는 data 속성을 대상으로 하는 사용자 지정 상태 변형을 만들고, 마크업에서 클래스 접두사로 사용합니다. 브라우저에서 직접 실행하는 실습 코드로 Tailwind CSS Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Tailwind CSS Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Tailwind CSS Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“플러그인으로 사용자 지정 변형 추가” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Tailwind CSS Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Tailwind CSS Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Tailwind 플러그인 API
  2. 플러그인으로 사용자 지정 유틸리티 추가
  3. 플러그인으로 사용자 지정 변형 추가
  4. 플러그인 게시 및 재사용
← Tailwind CSS Academy(으)로 돌아가기