通过插件添加自定义变体
使用 addVariant 创建自定义状态变体,定位 .is-active 等选择器或 data 属性,并在标记中将它们用作类名前缀。
通过插件添加自定义变体 是 CoddyKit 上的免费 Tailwind CSS Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 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 导师)并解锁 Tailwind CSS Academy 课程的其余内容,请升级到 CoddyKit PRO。 Tailwind CSS Academy 课程共包含 4 节课。
「通过插件添加自定义变体」这节课中我会学到什么?
使用 addVariant 创建自定义状态变体,定位 .is-active 等选择器或 data 属性,并在标记中将它们用作类名前缀。 你通过在浏览器中直接运行的动手代码来练习 Tailwind CSS Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Tailwind CSS Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Tailwind CSS Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「通过插件添加自定义变体」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Tailwind CSS Academy 课中编写并运行代码吗?
能。每节 Tailwind CSS Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Tailwind 插件 API
- 通过插件添加自定义工具类
- 通过插件添加自定义变体
- 发布并复用插件