Core concepts
Using utilities to style elements on hover, focus, and more.
Every utility class in Tailwind can be applied conditionally by adding a variant to the beginning of the class name that describes the condition you want to target.
For example, to apply the bg-sky-700
class on hover, use the hover:bg-sky-700
class:
Hover over this button to see the background color change
When writing CSS the traditional way, a single class name would do different things based on the current state:
Traditionally the same class name applies different styles on hover
.btn-primary { background-color: #0ea5e9;}.btn-primary:hover { background-color: #0369a1;}
In Tailwind, rather than adding the styles for a hover state to an existing class, you add another class to the element that only does something on hover:
In Tailwind, separate classes are used for the default state and the hover state
.bg-sky-500 { background-color: #0ea5e9;}.hover\:bg-sky-700:hover { background-color: #0369a1;}
Notice how hover:bg-sky-700
only defines styles for the :hover
state? It does nothing by default, but as soon as you hover over an element with that class, the background color will change to sky-700
.
This is what we mean when we say a utility class can be applied conditionally — by using variants you can control exactly how your design behaves in different states, without ever leaving your HTML.
Tailwind includes variants for just about everything you'll ever need, including:
:hover
, :focus
, :first-child
, and :required
::before
, ::after
, ::placeholder
, and ::selection
prefers-reduced-motion
[dir="rtl"]
and [open]
& > *
and & *
These variants can even be stacked to target more specific situations, for example changing the background color in dark mode, at the medium breakpoint, on hover:
<button class="dark:md:hover:bg-fuchsia-600 ...">Save changes</button>
In this guide you'll learn about every variant available in the framework, how to use them with your own custom classes, and even how to create your own.
Style elements on hover, focus, and active using the hover
, focus
, and active
variants:
Try interacting with this button to see the hover, focus, and active states
Tailwind also includes variants for other interactive states like :visited
, :focus-within
, :focus-visible
, and more.
See the pseudo-class reference for a complete list of available pseudo-class variants.
Style an element when it is the first-child or last-child using the first
and last
variants:
You can also style an element when it's an odd or even child using the odd
and even
variants:
Name | Title | |
---|---|---|
Jane Cooper | Regional Paradigm Technician | jane.cooper@example.com |
Cody Fisher | Product Directives Officer | cody.fisher@example.com |
Leonard Krasner | Senior Designer | leonard.krasner@example.com |
Emily Selman | VP, Hardware Engineering | emily.selman@example.com |
Anna Roberts | Chief Strategy Officer | anna.roberts@example.com |
<table> <!-- ... --> <tbody> {#each people as person} <!-- Use different background colors for odd and even rows --> <tr class="odd:bg-white even:bg-gray-50 dark:odd:bg-gray-900/50 dark:even:bg-gray-950"> <td>{person.name}</td> <td>{person.title}</td> <td>{person.email}</td> </tr> {/each} </tbody></table>
Use the nth-*
and nth-last-*
variants to style children based on their position in the list:
<div class="nth-3:underline"> <!-- ... --></div><div class="nth-last-5:underline"> <!-- ... --></div><div class="nth-of-type-4:underline"> <!-- ... --></div><div class="nth-last-of-type-6:underline"> <!-- ... --></div>
You can pass any number you want to these by default, and use arbitrary values for more complex expressions like nth-[2n+1_of_li]
.
Tailwind also includes variants for other structural pseudo-classes like :only-child
, :first-of-type
, :empty
, and more.
See the pseudo-class reference for a complete list of available pseudo-class variants.
Style form elements in different states using variants like required
, invalid
, and disabled
:
Try making the email address valid to see the styles change
Using variants for this sort of thing can reduce the amount of conditional logic in your templates, letting you use the same set of classes regardless of what state an input is in and letting the browser apply the right styles for you.
Tailwind also includes variants for other form states like :read-only
, :indeterminate
, :checked
, and more.
See the pseudo-class reference for a complete list of available pseudo-class variants.
Use the has-*
variant to style an element based on the state or content of its descendants:
You can use has-*
with a pseudo-class, like has-[:focus]
, to style an element based on the state of its descendants. You can also use element selectors, like has-[img]
or has-[a]
, to style an element based on the content of its descendants.
If you need to style an element based on the descendants of a parent element, you can mark the parent with the group
class and use the group-has-*
variant to style the target element:
If you need to style an element based on the descendants of a sibling element, you can mark the sibling with the peer
class and use the peer-has-*
variant to style the target element:
Use the not-
variant to style an element when a condition is not true.
It's particularly powerful when combined with other pseudo-class variants, for example combining not-focus:
with hover:
to only apply hover styles when an element is not focused:
Try focusing on the button and then hovering over it
You can also combine the not-
variant with media query variants like forced-colors
or supports
to only style an element when something about the user's environment is not true:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>
When you need to style an element based on the state of some parent element, mark the parent with the group
class, and use group-*
variants like group-hover
to style the target element:
Hover over the card to see both text elements change color
This pattern works with every pseudo-class variant, for example group-focus
, group-active
, or even group-odd
.
When nesting groups, you can style something based on the state of a specific parent group by giving that parent a unique group name using a group/{name}
class, and including that name in variants using classes like group-hover/{name}
:
Groups can be named however you like and don’t need to be configured in any way — just name your groups directly in your markup and Tailwind will automatically generate the necessary CSS.
You can create one-off group-*
variants on the fly by providing your own selector as an arbitrary value between square brackets:
<div class="group is-published"> <div class="hidden group-[.is-published]:block"> Published </div></div>
For more control, you can use the &
character to mark where .group
should end up in the final selector relative to the selector you are passing in:
<div class="group"> <div class="group-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>
The in-*
variant works similarly to group
except you don't need to add group
to the parent element:
<div tabindex="0" class="group"> <div class="opacity-50 group-focus:opacity-100"> <div tabindex="0"> <div class="opacity-50 in-focus:opacity-100"> <!-- ... --> </div> </div> </div></div>
The in-*
variant responds to state changes in any parent, so if you want more fine-grained control you'll need to use group
instead.
When you need to style an element based on the state of a sibling element, mark the sibling with the peer
class, and use peer-*
variants like peer-invalid
to style the target element:
Try making the email address valid to see the warning disappear
This makes it possible to do all sorts of neat tricks, like floating labels for example without any JS.
This pattern works with every pseudo-class variant, for example peer-focus
, peer-required
, and peer-disabled
.
It's important to note that the peer
marker can only be used on previous siblings because of how the subsequent-sibling combinator works in CSS:
Won't work, only previous siblings can be marked as peers
<label> <span class="peer-invalid:text-red-500 ...">Email</span> <input type="email" class="peer ..." /></label>
When using multiple peers, you can style something on the state of a specific peer by giving that peer a unique name using a peer/{name}
class, and including that name in variants using classes like peer-checked/{name}
:
Peers can be named however you like and don’t need to be configured in any way — just name your peers directly in your markup and Tailwind will automatically generate the necessary CSS.
You can create one-off peer-*
variants on the fly by providing your own selector as an arbitrary value between square brackets:
<form> <label for="email">Email:</label> <input id="email" name="email" type="email" class="is-dirty peer" required /> <div class="peer-[.is-dirty]:peer-required:block hidden">This field is required.</div> <!-- ... --></form>
For more control, you can use the &
character to mark where .peer
should end up in the final selector relative to the selector you are passing in:
<div> <input type="text" class="peer" /> <div class="hidden peer-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>
Style the ::before
and ::after
pseudo-elements using the before
and after
variants:
When using these variants, Tailwind will automatically add content: ''
by default so you don't have to specify it unless you want a different value:
It's worth noting that you don't really need ::before
and ::after
pseudo-elements for most things in Tailwind projects — it's usually simpler to just use a real HTML element.
For example, here's the same design from above but using a <span>
instead of the ::before
pseudo-element, which is a little easier to read and is actually less code:
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic"> When you look <span class="relative"> <span class="absolute -inset-1 block -skew-y-3 bg-pink-500" aria-hidden="true"></span> <span class="relative text-white">annoyed</span> </span> all the time, people think that you're busy.</blockquote>
Save before
and after
for situations where it's important that the content of the pseudo-element is not actually in the DOM and can't be selected by the user.
Style the placeholder text of any input or textarea using the placeholder
variant:
Style the button in file inputs using the file
variant:
Style the counters or bullets in lists using the marker
variant:
We've designed the marker
variant to be inheritable, so although you can use it directly on an <li>
element, you can also use it on a parent to avoid repeating yourself.
Style the active text selection using the selection
variant:
Try selecting some of this text with your mouse
We've designed the selection
variant to be inheritable, so you can add it anywhere in the tree and it will be applied to all descendant elements.
This makes it easy to set the selection color to match your brand across your entire site:
<html> <head> <!-- ... --> </head> <body class="selection:bg-pink-300"> <!-- ... --> </body></html>
Style the first line in a block of content using the first-line
variant, and the first letter using the first-letter
variant:
Style the backdrop of a native <dialog>
element using the backdrop
variant:
<dialog class="backdrop:bg-gray-50"> <form method="dialog"> <!-- ... --> </form></dialog>
If you're using native <dialog>
elements in your project, you may also want to read about styling open/closed states using the open
variant.
To style an element at a specific breakpoint, use responsive variants like md
and lg
.
For example, this will render a 3-column grid on mobile, a 4-column grid on medium-width screens, and a 6-column grid on large-width screens:
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6"> <!-- ... --></div>
To style an element based on the width of a parent element instead of the viewport, use variants like @md
and @lg
:
<div class="@container"> <div class="flex flex-col @md:flex-row"> <!-- ... --> </div></div>
Check out the Responsive design documentation for an in-depth look at how these features work.
The prefers-color-scheme
media query tells you whether the user prefers a light theme or dark theme, and is usually configured at the operating system level.
Use utilities with no variant to target light mode, and use the dark
variant to provide overrides for dark mode:
Check out the Dark Mode documentation for an in-depth look at how this feature works.
The prefers-reduced-motion
media query tells you if the user has requested that you minimize non-essential motion.
Use the motion-reduce
variant to conditionally add styles when the user has requested reduced motion:
Try emulating `prefers-reduced-motion: reduce` in your developer tools to hide the spinner
Tailwind also includes a motion-safe
variant that only adds styles when the user has not requested reduced motion. This can be useful when using the motion-reduce
helper would mean having to "undo" a lot of styles:
<!-- Using `motion-reduce` can mean lots of "undoing" styles --><button class="transition hover:-translate-y-0.5 motion-reduce:transition-none motion-reduce:hover:translate-y-0 ..."> Save changes</button><!-- Using `motion-safe` is less code in these situations --><button class="motion-safe:transition motion-safe:hover:-translate-x-0.5 ...">Save changes</button>
The prefers-contrast
media query tells you if the user has requested more or less contrast.
Use the contrast-more
variant to conditionally add styles when the user has requested more contrast:
Try emulating `prefers-contrast: more` in your developer tools to see the changes
Tailwind also includes a contrast-less
variant you can use to conditionally add styles when the user has requested less contrast.
The forced-colors
media query indicates if the user is using a forced colors mode. These modes override your site's colors with a user defined palette for text, backgrounds, links and buttons.
Use the forced-colors
variant to conditionally add styles when the user has enabled a forced color mode:
Try emulating `forced-colors: active` in your developer tools to see the changes
Use the not-forced-colors
variant to apply styles based when the user is not using a forced colors mode:
<div class="not-forced-colors:appearance-none ..."> <!-- ... --></div>
Tailwind also includes a forced color adjust utilities to opt in and out of forced colors.
Use the portrait
and landscape
variants to conditionally add styles when the viewport is in a specific orientation:
<div> <div class="portrait:hidden"> <!-- ... --> </div> <div class="landscape:hidden"> <p>This experience is designed to be viewed in landscape. Please rotate your device to view the site.</p> </div></div>
Use the print
variant to conditionally add styles that only apply when the document is being printed:
<div> <article class="print:hidden"> <h1>My Secret Pizza Recipe</h1> <p>This recipe is a secret, and must not be shared with anyone</p> <!-- ... --> </article> <div class="hidden print:block">Are you seriously trying to print this? It's secret!</div></div>
Use the supports-[...]
variant to style things based on whether a certain feature is supported in the user's browser:
<div class="flex supports-[display:grid]:grid ..."> <!-- ... --></div>
Under the hood the supports-[...]
variant generates @supports rules
and takes anything you’d use with @supports (...)
between the square brackets, like a property/value pair, and even expressions using and
and or
.
For terseness, if you only need to check if a property is supported (and not a specific value), you can just specify the property name:
<div class="bg-black/75 supports-backdrop-filter:bg-black/25 supports-backdrop-filter:backdrop-blur ..."> <!-- ... --></div>
Use the not-supports-[...]
variant to style things based on whether a certain feature is not supported in the user's browser:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>
You can configure shortcuts for common @supports
rules you're using in your project by creating a new variant in the supports-*
namespace:
@custom-variant supports-grid { @supports (display: grid) { @slot; }}
You can then use these custom supports-*
variants in your project:
<div class="supports-grid:grid"> <!-- ... --></div>
Use the starting
variant to set the appearance of an element when it is first rendered in the DOM, or transitions from display: none
to visible:
Use the aria-*
variant to conditionally style things based on ARIA attributes.
For example, to apply the bg-sky-700
class when the aria-checked
attribute is set to true
, use the aria-checked:bg-sky-700
class:
<div aria-checked="true" class="bg-gray-600 aria-checked:bg-sky-700"> <!-- ... --></div>
By default we've included variants for the most common boolean ARIA attributes:
Variant | CSS |
---|---|
aria-busy | &[aria-busy="true"] |
aria-checked | &[aria-checked="true"] |
aria-disabled | &[aria-disabled="true"] |
aria-expanded | &[aria-expanded="true"] |
aria-hidden | &[aria-hidden="true"] |
aria-pressed | &[aria-pressed="true"] |
aria-readonly | &[aria-readonly="true"] |
aria-required | &[aria-required="true"] |
aria-selected | &[aria-selected="true"] |
You can customize which aria-*
variants are available by creating a new variant:
@custom-variant aria-asc (&[aria-sort="ascending"]);@custom-variant aria-desc (&[aria-sort="descending"]);
If you need to use a one-off aria
variant that doesn’t make sense to include in your project, or for more complex ARIA attributes that take specific values, use square brackets to generate a property on the fly using any arbitrary value:
Invoice # | Client | Amount |
---|---|---|
#100 | Pendant Publishing | $2,000.00 |
#101 | Kruger Industrial Smoothing | $545.00 |
#102 | J. Peterman | $10,000.25 |
<table> <thead> <tr> <th aria-sort="ascending" class="aria-[sort=ascending]:bg-[url('/img/down-arrow.svg')] aria-[sort=descending]:bg-[url('/img/up-arrow.svg')]" > Invoice # </th> <!-- ... --> </tr> </thead> <!-- ... --></table>
ARIA state variants can also target parent and sibling elements using the group-aria-*
and peer-aria-*
variants:
<table> <thead> <tr> <th aria-sort="ascending" class="group"> Invoice # <svg class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"><!-- ... --></svg> </th> <!-- ... --> </tr> </thead> <!-- ... --></table>
Use the data-*
variant to conditionally apply styles based on data attributes.
To check if a data attribute exists (and not a specific value), you can just specify the attribute name:
<!-- Will apply --><div data-active class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div><!-- Will not apply --><div class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div>
If you need to check for a specific value you may use an arbitrary value:
<!-- Will apply --><div data-size="large" class="data-[size=large]:p-8"> <!-- ... --></div><!-- Will not apply --><div data-size="medium" class="data-[size=large]:p-8"> <!-- ... --></div>
Alternatively, you can configure shortcuts for common data attributes you're using in your project by creating a new variant in the data-*
namespace:
@import "tailwindcss";@custom-variant data-checked (&[data-ui~="checked"]);
You can then use these custom data-*
variants in your project:
<div data-ui="checked active" class="data-checked:underline"> <!-- ... --></div>
Use the rtl
and ltr
variants to conditionally add styles in right-to-left and left-to-right modes respectively when building multi-directional layouts:
Remember, these variants are only useful if you are building a site that needs to support both left-to-right and right-to-left layouts. If you're building a site that only needs to support a single direction, you don't need these variants — just apply the styles that make sense for your content.
Use the open
variant to conditionally add styles when a <details>
or <dialog>
element is in an open state:
Try toggling the disclosure to see the styles change
This variant also targets the :popover-open
pseudo-class for popovers:
<div> <button popovertarget="my-popover">Open Popover</button> <div popover id="my-popover" class="opacity-0 open:opacity-100 ..."> <!-- ... --> </div></div>
The inert
variant lets you style elements marked with the inert
attribute:
This is useful for adding visual cues that make it clear that sections of content aren't interactive.
While it's generally preferable to put utility classes directly on child elements, you can use the *
variant in situations where you need to style direct children that you don’t have control over:
It's important to note that overriding a style with a utility directly on the child itself won't work due to the specificity of the generated child selector:
Won't work, children can't override their own styling.
<ul class="*:bg-sky-50 ..."> <li class="bg-red-50 ...">Sales</li> <li>Marketing</li> <li>SEO</li> <!-- ... --></ul>
Like *
, the **
variant can be used to style children of an element. The main difference is that **
will apply styles to all descendants, not just the direct children. This is especially useful when you combine it with another variant for narrowing the thing you're selecting:
Just like arbitrary values let you use custom values with your utility classes, arbitrary variants let you write custom selector variants directly in your HTML.
Arbitrary variants are just format strings that represent the selector, wrapped in square brackets. For example, this arbitrary variant changes the cursor to grabbing
when the element has the is-dragging
class:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:cursor-grabbing">{item}</li> {/each}</ul>
Arbitrary variants can be stacked with built-in variants or with each other, just like the rest of the variants in Tailwind:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:active:cursor-grabbing">{item}</li> {/each}</ul>
If you need spaces in your selector, you can use an underscore. For example, this arbitrary variant selects all p
elements within the element where you've added the class:
<div class="[&_p]:mt-4"> <p>Lorem ipsum...</p> <ul> <li> <p>Lorem ipsum...</p> </li> <!-- ... --> </ul></div>
You can also use at-rules like @media
or @supports
in arbitrary variants:
<div class="flex [@supports(display:grid)]:grid"> <!-- ... --></div>
With at-rule custom variants the &
placeholder isn't necessary, just like when nesting with a preprocessor.
If you find yourself using the same arbitrary variant multiple times in your project, it might be worth creating a custom variant:
@custom-variant pointer-coarse { @media (pointer: coarse) { @slot; }}
Now you can use the pointer-coarse:<utility>
variant in your HTML:
<button class="pointer-coarse:size-12 ..."></button>
You can create variants using the shorthand syntax when nesting isn't required:
@custom-variant pointer-coarse (@media (pointer: coarse));
When a custom variant has multiple rules, they can be nested within each other:
@custom-variant any-hover { @media (any-hover: hover) { &:hover { @slot; } }}
A quick reference table of every single variant included in Tailwind by default.
Variant | CSS |
---|---|
hover | @media (hover: hover) { &:hover } |
focus | &:focus |
focus-within | &:focus-within |
focus-visible | &:focus-visible |
active | &:active |
visited | &:visited |
target | &:target |
* | :is(& > *) |
** | :is(& *) |
has-[...] | &:has(...) |
group-[...] | &:is(:where(.group)... *) |
peer-[...] | &:is(:where(.peer)... ~ *) |
in-[...] | :where(...) & |
not-[...] | &:not(...) |
inert | &:is([inert], [inert] *) |
first | &:first-child |
last | &:last-child |
only | &:only-child |
odd | &:nth-child(odd) |
even | &:nth-child(even) |
first-of-type | &:first-of-type |
last-of-type | &:last-of-type |
only-of-type | &:only-of-type |
nth-[...] | &:nth-child(...) |
nth-last-[...] | &:nth-last-child(...) |
nth-of-type-[...] | &:nth-of-type(...) |
nth-last-of-type-[...] | &:nth-last-of-type(...) |
empty | &:empty |
disabled | &:disabled |
enabled | &:enabled |
checked | &:checked |
indeterminate | &:indeterminate |
default | &:default |
optional | &:optional |
required | &:required |
valid | &:valid |
invalid | &:invalid |
in-range | &:in-range |
out-of-range | &:out-of-range |
placeholder-shown | &:placeholder-shown |
autofill | &:autofill |
read-only | &:read-only |
before | &::before |
after | &::after |
first-letter | &::first-letter |
first-line | &::first-line |
marker | &::marker, & *::marker |
selection | &::selection |
file | &::file-selector-button |
backdrop | &::backdrop |
placeholder | &::placeholder |
sm | @media (width >= 40rem) |
md | @media (width >= 48rem) |
lg | @media (width >= 64rem) |
xl | @media (width >= 80rem) |
2xl | @media (width >= 96rem) |
min-[...] | @media (width >= ...) |
max-sm | @media (width < 40rem) |
max-md | @media (width < 48rem) |
max-lg | @media (width < 64rem) |
max-xl | @media (width < 80rem) |
max-2xl | @media (width < 96rem) |
max-[...] | @media (width < ...) |
@3xs | @container (width >= 16rem) |
@2xs | @container (width >= 18rem) |
@xs | @container (width >= 20rem) |
@sm | @container (width >= 24rem) |
@md | @container (width >= 28rem) |
@lg | @container (width >= 32rem) |
@xl | @container (width >= 36rem) |
@2xl | @container (width >= 42rem) |
@3xl | @container (width >= 48rem) |
@4xl | @container (width >= 56rem) |
@5xl | @container (width >= 64rem) |
@6xl | @container (width >= 72rem) |
@7xl | @container (width >= 80rem) |
@min-[...] | @container (width >= ...) |
@max-3xs | @container (width < 16rem) |
@max-2xs | @container (width < 18rem) |
@max-xs | @container (width < 20rem) |
@max-sm | @container (width < 24rem) |
@max-md | @container (width < 28rem) |
@max-lg | @container (width < 32rem) |
@max-xl | @container (width < 36rem) |
@max-2xl | @container (width < 42rem) |
@max-3xl | @container (width < 48rem) |
@max-4xl | @container (width < 56rem) |
@max-5xl | @container (width < 64rem) |
@max-6xl | @container (width < 72rem) |
@max-7xl | @container (width < 80rem) |
@max-[...] | @container (width < ...) |
dark | @media (prefers-color-scheme: dark) |
portrait | @media (orientation: portrait) |
landscape | @media (orientation: landscape) |
motion-safe | @media (prefers-reduced-motion: no-preference) |
motion-reduce | @media (prefers-reduced-motion: reduce) |
contrast-more | @media (prefers-contrast: more) |
contrast-less | @media (prefers-contrast: less) |
@media print | |
supports-[…] | @supports (…) |
aria-busy | &[aria-busy="true"] |
aria-checked | &[aria-checked="true"] |
aria-disabled | &[aria-disabled="true"] |
aria-expanded | &[aria-expanded="true"] |
aria-hidden | &[aria-hidden="true"] |
aria-pressed | &[aria-pressed="true"] |
aria-readonly | &[aria-readonly="true"] |
aria-required | &[aria-required="true"] |
aria-selected | &[aria-selected="true"] |
aria-[…] | &[aria-…] |
data-[...] | &[data-...] |
rtl | [dir="rtl"] & |
ltr | [dir="ltr"] & |
open | &:is([open], :popover-open) |
forced-colors | @media (forced-colors: active) |
starting | @starting-style |
This is a comprehensive list of examples for all the pseudo-class variants included in Tailwind to complement the pseudo-classes documentation at the beginning of this guide.
Style an element when the user hovers over it with the mouse cursor using the hover
variant:
<div class="bg-black hover:bg-white ..."> <!-- ... --></div>
Style an element when it has focus using the focus
variant:
<input class="border-gray-300 focus:border-blue-400 ..." />
Style an element when it or one of its descendants has focus using the focus-within
variant:
<div class="focus-within:shadow-lg ..."> <input type="text" /></div>
Style an element when it has been focused using the keyboard using the focus-visible
variant:
<button class="focus-visible:outline-2 ...">Submit</button>
Style an element when it is being pressed using the active
variant:
<button class="bg-blue-500 active:bg-blue-600 ...">Submit</button>
Style a link when it has already been visited using the visited
variant:
<a href="https://seinfeldquotes.com" class="text-blue-600 visited:text-purple-600 ..."> Inspiration </a>
Style an element if its ID matches the current URL fragment using the target
variant:
<div id="about" class="target:shadow-lg ..."> <!-- ... --></div>
Style an element if it's the first child using the first
variant:
<ul> {#each people as person} <li class="py-4 first:pt-0 ..."> <!-- ... --> </li> {/each}</ul>
Style an element if it's the last child using the last
variant:
<ul> {#each people as person} <li class="py-4 last:pb-0 ..."> <!-- ... --> </li> {/each}</ul>
Style an element if it's the only child using the only
variant:
<ul> {#each people as person} <li class="py-4 only:py-0 ..."> <!-- ... --> </li> {/each}</ul>
Style an element if it's an oddly numbered child using the odd
variant:
<table> {#each people as person} <tr class="bg-white odd:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>
Style an element if it's an evenly numbered child using the even
variant:
<table> {#each people as person} <tr class="bg-white even:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>
Style an element if it's the first child of its type using the first-of-type
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="ml-2 first-of-type:ml-6 ..."> <!-- ... --> </a> {/each}</nav>
Style an element if it's the last child of its type using the last-of-type
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mr-2 last-of-type:mr-6 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element if it's the only child of its type using the only-of-type
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 only-of-type:mx-6 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element at a specific position using the nth
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-3:mx-6 nth-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element at a specific position from the end using the nth-last
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-3:mx-6 nth-last-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element at a specific position, of the same type using the nth-of-type
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-of-type-3:mx-6 nth-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element at a specific position from the end, of the same type using the nth-last-of-type
variant:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-of-type-3:mx-6 nth-last-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Style an element if it has no content using the empty
variant:
<ul> {#each people as person} <li class="empty:hidden ...">{person.hobby}</li> {/each}</ul>
Style an input when it's disabled using the disabled
variant:
<input class="disabled:opacity-75 ..." />
Style an input when it's enabled using the enabled
variant, most helpful when you only want to apply another style when an element is not disabled:
<input class="enabled:hover:border-gray-400 disabled:opacity-75 ..." />
Style a checkbox or radio button when it's checked using the checked
variant:
<input type="checkbox" class="appearance-none checked:bg-blue-500 ..." />
Style a checkbox or radio button in an indeterminate state using the indeterminate
variant:
<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />
Style an option, checkbox or radio button that was the default value when the page initially loaded using the default
variant:
<input type="checkbox" class="default:outline-2 ..." />
Style an input when it's optional using the optional
variant:
<input class="optional:border-red-500 ..." />
Style an input when it's required using the required
variant:
<input class="required:border-red-500 ..." />
Style an input when it's valid using the valid
variant:
<input class="valid:border-green-500 ..." />
Style an input when it's invalid using the invalid
variant:
<input class="invalid:border-red-500 ..." />
Style an input when its value is within a specified range limit using the in-range
variant:
<input min="1" max="5" class="in-range:border-green-500 ..." />
Style an input when its value is outside of a specified range limit using the out-of-range
variant:
<input min="1" max="5" class="out-of-range:border-red-500 ..." />
Style an input when the placeholder is shown using the placeholder-shown
variant:
<input class="placeholder-shown:border-gray-500 ..." placeholder="you@example.com" />
Style an input when it has been autofilled by the browser using the autofill
variant:
<input class="autofill:bg-yellow-200 ..." />
Style an input when it is read-only using the read-only
variant:
<input class="read-only:bg-gray-100 ..." />
From the creators of Tailwind CSS
Make your ideas look awesome, without relying on a designer.
“This is the survival kit I wish I had when I started building apps.”
Derrick Reimer, SavvyCal