@variant & @custom-variant

Invent Your Own Variant Prefixes

@variant & @custom-variant

Create reusable variants such as a class-based dark mode or an app-specific state with @custom-variant, and apply them in CSS with @variant.

4 min read Level 3/5 #tailwind#variants#customization
What you'll learn
  • Define a class-based dark variant with @custom-variant
  • Create app-specific state variants
  • Use @variant inside custom CSS rules

Variants are the prefixes like hover: and md:. @custom-variant lets you define new ones from any selector, and @variant lets you use a variant inside hand-written CSS.

Class-Based Dark Mode

By default dark: follows the OS setting. To make it toggle from a .dark class instead, redefine the variant:

@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

Now dark:bg-gray-900 applies whenever an ancestor carries the dark class, which a theme toggle can add or remove. The :where() wrapper keeps specificity at zero so utilities still override cleanly.

App-Specific Variants

Any selector you can write becomes a variant. A variant that activates when the sidebar is open:

@custom-variant sidebar-open (body:has(.sidebar-open) &);
@custom-variant aria-current (&[aria-current="page"]);
<main class="ml-0 sidebar-open:ml-64 transition-[margin]">
  Shifts when the sidebar opens
</main>

@variant Inside CSS

When you write a custom component class, @variant applies a variant to a block of declarations:

.btn {
  background: var(--color-blue-600);
  color: white;

  @variant dark {
    background: black;
  }

  @variant hover {
    background: var(--color-blue-700);
  }
}

This keeps variant logic consistent between utilities and your own CSS, with no media-query or selector duplication to maintain by hand.

Arbitrary Values & Properties →