Plugins let you register new utilities, components, variants, and more using JavaScript. This gives you complete control over extending Tailwind’s functionality.
Plugin API Overview
The plugin API provides these methods:
Register new utility classes api . addUtilities ({ '.scrollbar-hide' : { 'scrollbar-width' : 'none' } })
Register utilities that accept values api . matchUtilities ({ skew : ( value ) => ({ transform: `skew( ${ value } )` }) })
Register new variants api . addVariant ( 'hocus' , [ '&:hover' , '&:focus' ])
Register variants that accept values api . matchVariant ( 'nth' , ( value ) => `&:nth-child( ${ value } )` )
Register component classes (same API as addUtilities) api . addComponents ({ '.btn' : { padding: '.5rem 1rem' } })
Access theme values const colors = api . theme ( 'colors' )
Access config values const prefix = api . config ( 'prefix' )
Creating a Simple Plugin
Here’s a basic plugin structure:
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
plugin ( function ({ addUtilities }) {
addUtilities ({
'.scrollbar-hide' : {
'scrollbar-width' : 'none' ,
'&::-webkit-scrollbar' : {
display: 'none' ,
},
},
})
}),
] ,
}
Usage:
< div class = "scrollbar-hide overflow-auto" >
Content with hidden scrollbar
</ div >
Adding Static Utilities
Add utilities with fixed styles:
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
plugin (({ addUtilities }) => {
addUtilities ({
'.text-balance' : {
'text-wrap' : 'balance' ,
},
'.text-pretty' : {
'text-wrap' : 'pretty' ,
},
'.perspective-1000' : {
perspective: '1000px' ,
},
})
}),
] ,
}
Match Utilities (Dynamic Values)
Create utilities that accept values:
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
plugin (({ matchUtilities , theme }) => {
matchUtilities (
{
perspective : ( value ) => ({
perspective: value ,
}),
},
{
values: theme ( 'perspective' ),
},
)
}),
] ,
}
With theme values:
export default {
theme: {
extend: {
perspective: {
'500' : '500px' ,
'1000' : '1000px' ,
'2000' : '2000px' ,
},
},
} ,
plugins: [ /* plugin above */ ] ,
}
Usage:
< div class = "perspective-1000" > 3D transform container </ div >
< div class = "perspective-[1500px]" > Arbitrary value </ div >
Match Utilities Options
The matchUtilities function accepts options:
import type { CSSRuleObject } from 'tailwindcss/types/config'
matchUtilities (
{
'gradient-angle' : ( value ) => ({
'--tw-gradient-angle' : value ,
} as CSSRuleObject ),
},
{
// Supported value types
type: [ 'angle' , 'length' ],
// Whether negative values should work (-gradient-angle-45)
supportsNegativeValues: true ,
// Named values
values: {
'0' : '0deg' ,
'45' : '45deg' ,
'90' : '90deg' ,
'180' : '180deg' ,
},
// Supported modifiers
modifiers: 'any' , // or { 'half': '50%' }
},
)
Type Parameter
The type parameter validates arbitrary values:
'any' - Any value is accepted
'color' - Colors only
'length' - Length values (px, rem, etc.)
'percentage' - Percentage values
'number' - Numbers
'angle' - Angle values (deg, rad, etc.)
Array of types: ['length', 'percentage']
Adding Variants
Create custom variants:
Static Variant
Functional Variant
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
plugin (({ addVariant }) => {
// Simple pseudo-class
addVariant ( 'hocus' , [ '&:hover' , '&:focus' ])
// Media query
addVariant ( 'supports-grid' , '@supports (display: grid)' )
// Attribute selector
addVariant ( 'optional' , '&:optional' )
// Child selector
addVariant ( 'child' , '& > *' )
}),
] ,
}
Accessing Theme Values
Access theme values in your plugin:
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
plugin (({ matchUtilities , theme }) => {
matchUtilities (
{
'border-gradient' : ( value ) => ({
'border-image' : `linear-gradient( ${ value } ) 1` ,
}),
},
{
values: theme ( 'colors' ),
type: 'color' ,
},
)
}),
] ,
}
Plugin with Configuration
Create plugins that accept configuration:
import plugin from 'tailwindcss/plugin'
import type { PluginAPI } from 'tailwindcss/types/config'
const myPlugin = plugin . withOptions <{ className ?: string }>(
( options = {}) => {
return ({ addUtilities } : PluginAPI ) => {
const className = options . className ?? 'custom'
addUtilities ({
[ `. ${ className } ` ]: {
display: 'flex' ,
'align-items' : 'center' ,
},
})
}
},
( options = {}) => {
return {
theme: {
extend: {
colors: {
custom: options . className ?? 'custom' ,
},
},
},
}
},
)
export default {
plugins: [
myPlugin ({ className: 'flex-center' }),
] ,
}
Real-World Plugin Examples
import plugin from 'tailwindcss/plugin'
const scrollbarPlugin = plugin (({ addUtilities , matchUtilities , theme }) => {
addUtilities ({
'.scrollbar-thin' : {
'scrollbar-width' : 'thin' ,
},
'.scrollbar-none' : {
'scrollbar-width' : 'none' ,
'&::-webkit-scrollbar' : {
display: 'none' ,
},
},
})
matchUtilities (
{
'scrollbar' : ( value ) => ({
'&::-webkit-scrollbar' : {
width: value ,
height: value ,
},
}),
'scrollbar-track' : ( value ) => ({
'&::-webkit-scrollbar-track' : {
'background-color' : value ,
},
}),
'scrollbar-thumb' : ( value ) => ({
'&::-webkit-scrollbar-thumb' : {
'background-color' : value ,
},
}),
},
{
values: theme ( 'colors' ),
type: 'color' ,
},
)
})
export default {
plugins: [ scrollbarPlugin ] ,
}
Text Shadow Plugin
import plugin from 'tailwindcss/plugin'
const textShadowPlugin = plugin (({ matchUtilities , theme }) => {
matchUtilities (
{
'text-shadow' : ( value ) => ({
'text-shadow' : value ,
}),
},
{
values: {
sm: '0 1px 2px rgb(0 0 0 / 0.5)' ,
DEFAULT: '0 2px 4px rgb(0 0 0 / 0.5)' ,
lg: '0 8px 16px rgb(0 0 0 / 0.5)' ,
},
},
)
})
Animation Delay Plugin
import plugin from 'tailwindcss/plugin'
const animationDelayPlugin = plugin (({ matchUtilities , theme }) => {
matchUtilities (
{
'animation-delay' : ( value ) => ({
'animation-delay' : value ,
}),
},
{
values: theme ( 'transitionDelay' ),
},
)
})
Distributing Plugins
Create a shareable plugin package:
import plugin from 'tailwindcss/plugin'
export default plugin (({ addUtilities , theme }) => {
// Your plugin code
} )
Package structure:
my-plugin/
├── index.ts
├── package.json
└── README.md
package.json:
{
"name" : "tailwindcss-my-plugin" ,
"version" : "1.0.0" ,
"main" : "index.ts" ,
"peerDependencies" : {
"tailwindcss" : ">=4.0.0"
}
}
Usage:
import myPlugin from 'tailwindcss-my-plugin'
export default {
plugins: [ myPlugin ] ,
}
Plugin Best Practices
Use TypeScript - Get type safety and better IDE support
Provide defaults - Make configuration optional with sensible defaults
Follow naming conventions - Use Tailwind’s naming patterns
Document thoroughly - Include usage examples and options
Test across browsers - Ensure cross-browser compatibility
When creating utilities that use modifiers (like opacity modifiers for colors), set modifiers: 'any' in the options to allow arbitrary modifier values.
Plugins run during build time. Avoid expensive operations or side effects that could slow down builds.