Pseudo-Class Variants
Similar to how Tailwind handles responsive design, styling elements on hover, focus, and more can be accomplished by prefixing utilities with the appropriate pseudo-class.
Not all pseudo-class variants are enabled for all utilities by default due to file-size considerations, but we’ve tried our best to enable the most commonly used combinations out of the box.
For a complete list of which variants are enabled by default, see the at the end of this page.
If you need to target a pseudo-class that Tailwind doesn’t support, you can extend the supported variants by writing a variant plugin.
Hover
Add the prefix to only apply a utility on hover.
<button class="bg-transparent hover:bg-blue-500 text-blue-700 hover:text-white...">
Hover me
</button>
You can control whether hover
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus'],
},
}
Focus
Add the focus:
prefix to only apply a utility on focus.
<input class="bg-gray-200 focus:bg-white border-transparent focus:border-blue-400 ..." placeholder="Focus me">
You can control whether focus
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus'],
},
}
Active
Add the active:
prefix to only apply a utility when an element is active.
<button class="bg-blue-500 active:bg-blue-700 text-white...">
Click me
</button>
You can control whether active
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'active'],
},
}
Group-hover
If you need to style a child element when hovering over a specific parent element, add the .group
class to the parent element and add the group-hover:
prefix to the utility on the child element.
<div class="group bg-white hover:bg-blue-500 ...">
<p class="text-gray-900 group-hover:text-white ...">New Project</p>
<p class="text-gray-700 group-hover:text-white ...">Create a new project from a variety of starting templates.</p>
</div>
You can control whether group-hover
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
},
}
Group-focusv1.3.0+
The group-focus
variant works just like group-hover
except for focus:
<button class="group text-gray-700 focus:text-gray-900 ...">
<svg class="h-6 w-6 text-gray-400 group-focus:text-gray-500"><!-- ... --></svg>
Submit
</button>
You can control whether group-focus
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
textColor: ['responsive', 'hover', 'focus', 'group-focus'],
},
}
Focus-within
Note that focus-within is not supported in IE or Edge < 79.
Add the focus-within:
prefix to only apply a utility when a child element has focus.
<form class="border-b-2 border-gray-400 focus-within:border-teal-500 ...">
<input class="..." placeholder="Jane Doe" ...>
<button class="...">
Sign Up
</button>
</form>
You can control whether focus-within
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
// ...
variants: {
borderColor: ['responsive', 'hover', 'focus', 'focus-within'],
},
}
Note that focus-visible currently requires a polyfill for sufficient browser support.
Add the focus-visible:
prefix to only apply a utility when an element has focus but only if the user is using the keyboard.
Note that currently only Firefox and Chrome support focus-visible
natively, so for sufficient browser support you should install and configure both the and the focus-visible PostCSS polyfill. Make sure to include the PostCSS plugin after Tailwind in your list of PostCSS plugins:
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
'postcss-focus-visible': {},
autoprefixer: {}
}
}
You can control whether variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
textDecoration: ['responsive', 'hover', 'focus', 'focus-visible'],
},
}
Motion-safev1.6.0+
Add the motion-safe:
prefix to only apply a utility when the prefers-reduced-motion
media feature matches no-preference
.
For example, this button will only animate on hover if the user hasn’t enabled “Reduce motion” on their system.
<button class="transform motion-safe:hover:-translate-y-1 motion-safe:hover:scale-110 transition ease-in-out duration-300 ...">
Hover
</button>
Note that unlike most other variants, motion-safe
can be combined with both responsive variants and other variants like hover
, by stacking them in this order:
<div class="sm:motion-safe:hover:animate-spin">
<!-- ... -->
</div>
You can control whether motion-safe
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
translate: ['responsive', 'hover', 'focus', 'motion-safe'],
},
}
Motion-reducev1.6.0+
Add the motion-reduce:
prefix to only apply a utility when the prefers-reduced-motion
media feature matches reduce
.
For example, this button will animate on hover by default, but the animations will be disabled if the user has enabled “Reduce motion” on their system.
<button class="transform motion-reduce:transform-none hover:-translate-y-1 hover:scale-110 transition ease-in-out duration-300 ...">
Hover
</button>
Note that unlike most other variants, motion-reduce
can be combined with both responsive variants and other variants like hover
, by stacking them in this order:
<div class="sm:motion-reduce:hover:animate-none">
<!-- ... -->
</div>
You can control whether motion-reduce
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
translate: ['responsive', 'hover', 'focus', 'motion-reduce'],
},
}
Disabledv1.1.0+
Add the disabled:
prefix to only apply a utility when an element is disabled.
<button class="disabled:opacity-75 bg-blue-500...">
Submit
</button>
<button disabled class="disabled:opacity-75 bg-blue-500...">
Submit
</button>
You can control whether disabled
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
opacity: ['responsive', 'hover', 'focus', 'disabled'],
},
}
Visitedv1.1.0+
Add the visited:
prefix to only apply a utility when a link has been visited.
<a href="#" class="text-blue-600 visited:text-purple-600 ...">Link</a>
You can control whether visited
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
textColor: ['responsive', 'hover', 'focus', 'visited'],
},
}
Checkedv1.5.0+
Add the checked:
prefix to only apply a utility when a radio or checkbox is currently checked.
You can control whether checked
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'checked'],
},
}
First-childv1.1.0+
Add the first:
prefix to only apply a utility when it is the first-child of its parent. This is mostly useful when elements are being generated in some kind of loop.
<div class="border rounded">
<div v-for="item in items" class="border-t first:border-t-0">
{{ item }}
</div>
It’s important to note that you should add any utilities to the child element, not the parent element.
You can control whether first
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
borderWidth: ['responsive', 'first', 'hover', 'focus'],
},
}
Add the last:
prefix to only apply a utility when it is the last-child of its parent. This is mostly useful when elements are being generated in some kind of loop.
<div class="border rounded">
<div v-for="item in items" class="border-b last:border-b-0">
{{ item }}
</div>
</div>
It’s important to note that you should add any last:
utilities to the child element, not the parent element.
// tailwind.config.js
module.exports = {
// ...
variants: {
borderWidth: ['responsive', 'last', 'hover', 'focus'],
},
}
Odd-childv1.1.0+
Add the odd:
prefix to only apply a utility when it is an odd-child of its parent. This is mostly useful when elements are being generated in some kind of loop.
<div class="border rounded">
<div v-for="item in items" class="bg-white odd:bg-gray-200">
{{ item }}
</div>
</div>
It’s important to note that you should add any odd:
utilities to the child element, not the parent element.
You can control whether odd
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'odd', 'hover', 'focus'],
},
}
Even-childv1.1.0+
Add the even:
prefix to only apply a utility when it is an even-child of its parent. This is mostly useful when elements are being generated in some kind of loop.
<div class="border rounded">
<div v-for="item in items" class="bg-white even:bg-gray-200">
{{ item }}
</div>
</div>
It’s important to note that you should add any even:
utilities to the child element, not the parent element.
You can control whether even
variants are enabled for a utility in the variants
section of your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'even', 'hover', 'focus'],
},
}
Combining with responsive prefixes
Pseudo-class variants are also responsive, meaning you can do things like change an element’s hover style at different breakpoints for example.
To apply a pseudo-class variant at a specific breakpoint, add the responsive prefix first, before the pseudo-class prefix:
all
sm
md
lg
xl
<div class="bg-orange-500 hover:bg-orange-600 sm:bg-green-500 sm:hover:bg-green-600 md:bg-red-500 md:hover:bg-red-600 lg:bg-indigo-500 lg:hover:bg-indigo-600 xl:bg-pink-500 xl:hover:bg-pink-600"></div>
Button
Generative variants for custom utilities
You can generate pseudo-class variants for your own custom utilities by wrapping them with the @variants
directive in your CSS:
/* Input: */
@variants group-hover, hover, focus {
.banana {
color: yellow;
}
}
/* Output: */
.banana {
color: yellow;
}
.group:hover .group-hover\:banana {
color: yellow;
}
.hover\:banana:hover {
color: yellow;
}
.focus\:banana:focus {
color: yellow;
}
For more information, see the .
Creating custom variants
You can create your own variants for any pseudo-classes Tailwind doesn’t include by default by writing a custom variant plugin.
For example, this simple plugin adds support for the disabled
pseudo-class variant:
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addVariant, e }) {
addVariant('disabled', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`disabled${separator}${className}`)}:disabled`
})
})
})
]
Learn more about writing variant plugins in the .
Default variants reference
Due to file-size considerations, Tailwind does not include all variants for all utilities by default.
To configure which variants are enabled for your project, see the .