Tailwind Utility Prefix Reference

Tailwind variant prefixes — hover, focus, dark, lg, aria — with selector output.

Reference for Tailwind CSS variant prefixes (hover, focus, dark, responsive, group, aria, data) with the generated CSS selector each produces, stacking order rules and JIT class-name builder. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is a Tailwind variant prefix?

A variant is a prefix added before a utility with a colon, like hover:bg-blue-500. It tells Tailwind to apply the utility only under a condition — a pseudo-class, media query or attribute selector. The base utility is unchanged.

What Tailwind variant prefixes do

Tailwind utility classes are unconditional by default — bg-blue-500 always applies. Variant prefixes make a utility conditional: hover:bg-blue-500 only paints on hover, md:bg-blue-500 only above the medium breakpoint, and dark:bg-blue-500 only in dark mode. This reference lists the common variants, the CSS selector or at-rule each compiles to, and how to stack them.

How Tailwind compiles variants

A variant is a prefix plus a colon. At build time, Tailwind’s JIT engine reads the class name, looks up the variant in its variant registry, and wraps the utility’s CSS declaration in the matching selector or at-rule:

/* hover:bg-blue-500 */
.hover\:bg-blue-500:hover { background-color: #3b82f6 }

/* md:flex */
@media (min-width: 768px) { .md\:flex { display: flex } }

/* dark:text-white (media strategy) */
@media (prefers-color-scheme: dark) { .dark\:text-white { color: #fff } }

/* focus-visible:ring-2 */
.focus-visible\:ring-2:focus-visible { --tw-ring-offset-shadow: ...; }

The backslash escaping in class names is automatic — you write the class with colons in HTML and Tailwind handles the CSS escaping.

Variant categories

State variants target pseudo-classes on the element itself:

VariantCompiles to
hover::hover
focus::focus
focus-visible::focus-visible
focus-within::focus-within
active::active
disabled::disabled
checked::checked
placeholder:::placeholder
first::first-child
last::last-child
odd: / even::nth-child(odd/even)

Responsive variants wrap in min-width media queries (mobile-first):

VariantBreakpoint
sm:>= 640px
md:>= 768px
lg:>= 1024px
xl:>= 1280px
2xl:>= 1536px

Theme variants:

VariantEffect
dark:@media (prefers-color-scheme: dark) or .dark class selector, depending on darkMode config
print:@media print
motion-safe:@media (prefers-reduced-motion: no-preference)
motion-reduce:@media (prefers-reduced-motion: reduce)

Group and peer variants for parent/sibling-driven styling:

VariantWhat it needsCompiles to
group-hover:group class on ancestor.group:hover .element
group-focus:group class on ancestor.group:focus .element
peer-checked:peer class on earlier sibling.peer:checked ~ .element
peer-focus:peer class on earlier sibling.peer:focus ~ .element

Attribute variants for DOM state without additional JavaScript:

VariantTargets
aria-expanded:[aria-expanded="true"]
aria-selected:[aria-selected="true"]
data-[state=open]:[data-state="open"] arbitrary data attribute

Stacking variants

Variants combine into a single condition when stacked. md:dark:hover:underline underlines only when all three hold simultaneously: viewport ≥ 768px, dark mode active, and element hovered.

Write stacked variants outer to inner: responsive → theme → state is the conventional order, e.g. lg:dark:hover:bg-brand-700. Tailwind does not enforce order for the generated CSS, but consistency in the codebase makes scanning class lists much easier.

Arbitrary variants

When no named variant covers your need, use square brackets to write any selector directly:

<li class="[&:nth-child(3)]:font-bold">
<div class="supports-[display:grid]:grid">
<p class="[@media(min-width:900px)]:text-xl">

The & represents the element. Use arbitrary variants sparingly — common patterns should use config extensions rather than one-off bracket syntax scattered across templates.