Skip to main content

Overview

Tailwind CSS provides two ways to create custom variants: @custom-variant for defining new variants and @variant for applying existing variants within custom utilities or other contexts.

@custom-variant Directive

The @custom-variant directive allows you to create entirely new variants that can be used throughout your project.

Body-less Syntax

The simplest way to define a variant is using the body-less syntax with a selector list.

Selector Variants

This creates a hocus: variant that applies styles when the element is hovered or focused.
The & symbol represents the element the utility is applied to. Multiple selectors are comma-separated.

At-Rule Variants

Mixed Selectors and At-Rules

You can combine both selector and at-rule conditions:

Body with @slot Syntax

For more complex variants, use the body syntax with @slot to mark where utilities should be inserted.

Basic @slot Usage

Nested Structures

Using @variant Inside Definitions

You can compose variants by using @variant within @custom-variant bodies:
This creates a variant that applies on both hover AND focus (different from the comma-separated version which is OR).
Be careful not to create circular dependencies when composing variants. The following would cause an error:

@variant Directive

The @variant directive applies an existing variant within custom utility or variant definitions.

In Custom Utilities

Apply variants directly in utility definitions:

Composing Multiple Variants

Nest @variant directives to combine conditions:

Compound Variants

Tailwind includes compound variants that modify how other variants work.

group Variant

The group compound variant is implemented in the source code:
Usage:

peer Variant

Similar to group, but for sibling elements:

not Variant

The not variant negates another variant:

in Variant

Applies styles when the element is inside another element:

has Variant

Applies styles when the element contains a matching child:

Variant Ordering

Variants have a specific order that determines their precedence:
Variants are applied in the order they’re defined in the framework, not the order they appear in your class names.

Advanced Variant Features

Functional Variants

Functional variants accept values:

Custom Dark Mode Variant

Override the default dark mode implementation:

Breakpoint-like Variants

Rules and Constraints

Important Rules:
  • @custom-variant must be defined at the top level (not nested)
  • Variant names must be alphanumeric, may contain dashes/underscores
  • Variant names must start with a lowercase letter or number
  • Variant names cannot end with a dash or underscore
  • Cannot have both a selector list and a body
  • Must have either a selector list or a body with @slot

Invalid Examples

Best Practices

Recommendations:
  1. Use descriptive names that clearly indicate when the variant applies
  2. Prefer body-less syntax for simple variants
  3. Use @slot syntax for complex structural variants
  4. Test variants with compound variants like group- and peer-
  5. Document complex variants with comments explaining their behavior
  6. Avoid creating variants that conflict with core variants

Source Code Reference

The variant system is implemented in:
  • /packages/tailwindcss/src/variants.ts:39-317 - Variants class
  • /packages/tailwindcss/src/variants.ts:348-1163 - createVariants function
  • /packages/tailwindcss/src/variants.ts:86-110 - fromAst method for @custom-variant
  • /packages/tailwindcss/src/variants.ts:1210-1235 - substituteAtVariant function