Extending Tailwind with your own custom utility classes.
Although Tailwind provides a pretty comprehensive set of utility classes out of the box, you may run into situations where you need to add a few of your own.
Deciding on the best way to extend a framework can be paralyzing, so here are some best practices to help you add your own utilities in the most idiomatic way possible.
The easiest way to add your own utilities to Tailwind is to simply add them to your CSS.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.scroll-snap-none {
scroll-snap-type: none;
}
.scroll-snap-x {
scroll-snap-type: x;
}
.scroll-snap-y {
scroll-snap-type: y;
}
}
By using the @layer
directive, Tailwind will automatically move those styles to the same place as @tailwind utilities
to avoid unintended specificity issues.
Using the @layer
directive will also instruct Tailwind to consider those styles for purging when purging the utilities
layer. Read our documentation on optimizing for production for more details.
If you'd like to generate responsive variants of your own utilities based on the breakpoints defined in your tailwind.config.js
file, wrap your utilities in the @variants
directive and add responsive
to the list of variants:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
@variants responsive {
.scroll-snap-none {
scroll-snap-type: none;
}
.scroll-snap-x {
scroll-snap-type: x;
}
.scroll-snap-y {
scroll-snap-type: y;
}
}
}
Tailwind will automatically generate prefixed versions of each custom utility that you can use to conditionally apply those styles at different breakpoints:
<!-- Use `scroll-snap-type: none` by default, then use `scroll-snap-type: x` on medium screens and up -->
<div class="scroll-snap-none md:scroll-snap-x"></div>
Learn more about responsive utilities in the responsive design documentation.
If you'd like to generate dark mode variants of your own utilities, first make sure darkMode
is set to either media
or class
in your tailwind.config.js
file:
// tailwind.config.js
module.exports = {
darkMode: 'media'
// ...
}
Next, wrap your utilities in the @variants
directive and add dark
to the list of variants:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
@variants dark {
.filter-none {
filter: none;
}
.filter-grayscale {
filter: grayscale(100%);
}
}
}
Tailwind will automatically generate prefixed versions of each custom utility that you can use to conditionally apply those styles at different states:
<div class="filter-grayscale dark:filter-none"></div>
Learn more about dark mode utilities in the dark mode documentation.
If you'd like to create state variants for your own utilities, wrap your utilities in the @variants
directive and list the variants you'd like to enable:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
@variants hover, focus {
.filter-none {
filter: none;
}
.filter-grayscale {
filter: grayscale(100%);
}
}
}
Tailwind will automatically generate prefixed versions of each custom utility that you can use to conditionally apply those styles at different states:
<div class="filter-grayscale hover:filter-none"></div>
State variants are generated in the same order you list them in the @variants
directive, so if you'd like one variant to take precedence over another, make sure you list that one last:
/* Focus will take precedence over hover */
@variants hover, focus {
.filter-grayscale {
filter: grayscale(100%);
}
/* ... */
}
/* Hover will take precedence over focus */
@variants focus, hover {
.filter-grayscale {
filter: grayscale(100%);
}
/* ... */
}
Learn more about state variants in the state variants documentation.
In addition to adding new utility classes directly in your CSS files, you can also add utilities to Tailwind by writing your own plugin:
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addUtilities }) {
const newUtilities = {
'.filter-none': {
filter: 'none',
},
'.filter-grayscale': {
filter: 'grayscale(100%)',
},
}
addUtilities(newUtilities, ['responsive', 'hover'])
})
]
}
This can be a good choice if you want to publish your custom utilities as a library or make it easier to share them across multiple projects.
Learn more in the utility plugin documentation.