Arbitrary variants extend the same square-bracket escape hatch to selectors and states, letting you apply a utility conditionally based on nearly any CSS selector, not just Tailwind's built-in variant list. This lesson covers the syntax and practical use cases.
What Are Arbitrary Variants?
Just as arbitrary values let you write a raw CSS value, arbitrary variants let you write a raw CSS selector or condition in square brackets before a utility, applying that utility only when the selector matches.
This covers cases Tailwind's built-in variants (hover:, focus:, md:, etc.) don't handle out of the box, like targeting a specific data attribute, a sibling combinator, or an unusual pseudo-class.
<ul>
<li class="[&:nth-child(3)]:font-bold">Third item is bold</li>
</ul>
[&:nth-child(3)] targets the exact CSS selector inside the brackets, applying font-bold only to the third list item.
The & represents the element itself within the bracketed selector.
Combine with pseudo-classes, attribute selectors, or child/sibling combinators as needed.
Works alongside responsive and state prefixes, like md:[&:first-child]:mt-0.
For simple, common needs, check if a built-in variant already covers it before reaching for this syntax.
Arbitrary Variants Cheatsheet
Common arbitrary variant patterns for custom selectors.
Example
Matches
[&:nth-child(odd)]:bg-slate-50
Every odd-numbered child
[&:first-child]:mt-0
Only the first child element
[&>*]:mx-2
Every direct child of the element
[&[data-state='open']]:block
Elements with a specific data attribute value
[&::placeholder]:text-slate-400
The placeholder pseudo-element
[&_p]:text-sm
Any descendant <p> element
has-[:checked]:bg-blue-50
Built-in has-* variant for a checked descendant
group-[.is-open]:rotate-180
A group ancestor matching a specific class
Styling Descendant Elements
The underscore-based descendant selector syntax lets you style elements you don't directly control, common when working with rendered Markdown or third-party component output where you can't add classes to inner elements.
<div class="[&_a]:text-blue-600 [&_a]:underline">
<!-- Any nested <a> tag gets styled, even without its own class -->
<p>Check out our <a href="/docs">documentation</a>.</p>
</div>
Targeting Pseudo-Elements
Some pseudo-elements, like ::placeholder or ::-webkit-scrollbar, aren't fully covered by Tailwind's built-in variants. Arbitrary variants let you target them directly.
Arbitrary variants can be chained with responsive and state prefixes in any order, giving you full flexibility for genuinely unusual conditions while still benefiting from Tailwind's existing variant system.
<li class="md:[&:nth-child(3)]:font-bold">
Bold only at md breakpoint and up, and only for the third item.
</li>
Common Mistakes
Reaching for an arbitrary variant when a built-in one (like first:, last:, or even:) already covers the exact same case.
Forgetting the & placeholder inside the brackets, which represents the element the class is applied to.
Writing overly complex selectors that would be clearer as a small custom plugin variant instead.
Not testing arbitrary variant selectors carefully, since a typo inside the brackets fails silently with no build error in some setups.
Overusing descendant selectors ([&_p]) as a substitute for properly structuring markup with classes where possible.
Key Takeaways
Arbitrary variants apply a utility based on a raw CSS selector written in square brackets.
The & symbol inside the brackets represents the current element.
They're useful for pseudo-elements, attribute selectors, and descendant styling Tailwind doesn't cover by default.
Arbitrary variants can be combined with responsive and state prefixes in any order.
Check for an existing built-in variant first; many common cases (first:, odd:, has-*:) are already covered.
Pro Tip
Before writing an arbitrary variant, search the Tailwind documentation for your exact need, variants like first:, odd:, has-*:, and group-*: cover far more cases than most developers initially expect.
You now understand Tailwind's arbitrary variant syntax. Next, learn advanced responsive design patterns beyond basic breakpoint prefixes.