Creating Tailwindcss Plugins
Writing your own Tailwindcss plugins - for lightning-fast creation and modification of styles.
Lightning-fast creation and modification of styles. But at what cost?
Let's take an example: we have a body element with a div inside it. You simply take the body tag, add something like class="flex" and instantly get the styling for a flexbox, then add justify-center and you've achieved the impossible - centering a div.
Recently, however, I was led on an adventure that I'd like to share with you.
Since Tailwindcss is so powerful while simultaneously having completely ephemeral properties, it means abstraction. Normally, I'd recommend taking a look at the Tailwindcss documentation, and in this case I do just that. In the case of plugins, however, I'd say their documentation is basically just the prelude.
But why do you need plugins?
First of all, I want to explain why I wanted to create a plugin.
Our design called for an extravagant animation, which I was able to create using linear-gradients. But this styling would have been pretty tedious to implement for multiple colors, buttons, and so on. It simply wasn't configurable, and like most programmers, I'm more afraid of writing the same line of code multiple times than of the wrath of the god Zeus himself.
So I began my journey by figuring out how to create a Tailwind plugin. As mentioned in the Tailwind docs, you simply need a function that you pass into the config, like this:
1const plugin = require('tailwindcss/plugin');2 3module.exports = {4 plugins: [5 plugin(function ({ addUtilities, addComponents, e, config }) {6 // Add your custom styles here7 }),8 ],9};
An extensive repository search later
After adding this, my basic need was to be able to override the colors in my linear-gradient. Well, that's where I ran my head into the wall.
There was absolutely no documentation on how to manipulate existing styles via the plugin function. The only thing they show is basically the creation of a normal CSS class styling.
After searching far and wide, I found two great repos that I used as a foundation. The first is very basic, but gives a good overview of the essentials.
The second, however, blew me away. It's a plugin for creating and managing CSS variables. Around 1000 lines of code, just for the logic of creating variables.
Not exactly what I needed, but it inspired me. From there, I started with a function that creates the basic Tailwind variables I need to override:
1type Color = [string, string]; // [colorName, colorValue] 2 3function getGradientStyling([key, value]: Color, e: (className: string) => string): CSSRuleObject { 4 return { 5 // create a new utility class for each key/color 6 [`.${e(`gradient-animate-${key}`)}`]: { 7 // overwrite the default tailwind variables for gradients 8 ['--tw-gradient-to']: `rgba(0,0,0,0) var(--tw-gradient-to-position)`, 9 ['--tw-gradient-from']: `${value} var(--tw-gradient-from-position)`,10 ['--tw-gradient-stops']: `var(--tw-gradient-from), ${value} var(--tw-gradient-via-position), var(--tw-gradient-to)`,11 },12 };13}
Essentially, it takes a name, which it would use to create the class, and a value for creating the variables within that class. This way we can use gradient-animate- + 'any color in our configuration' and it works right away.
The next step was honestly the most annoying part. I did my best to avoid this aspect. Naturally, I now needed an array with all my colors. The Tailwind plugin functions have access to the theme, so using something like theme(colors) gives you access to all the colors in the configuration, like here:
1module.exports = { 2 theme: { 3 colors: { 4 primary: { DEFAULT: '#F9F6EE' }, 5 secondary: { DEFAULT: '#E5D8C7', light: '#EEE4D6' }, 6 tertiary: { green: '#B4D59A', yellow: '#FECF55', red: '#DD6972' }, 7 stroke: '#B5B5B526', 8 white: '#FFF', 9 black: '#232323',10 gray: { DEFAULT: '#979797', light: '#CDCDCD' },11 current: 'currentColor',12 transparent: 'transparent',13 },14 },15 plugins: [16 ...,17 ],18};
However, processing these is a whole different story. I had hoped Tailwind had a helper function, but I couldn't find any information about it, so I created my own solution:
1function getColors(object: Record<string, string | object> | object, parentKey: string): Color[] { 2 let colorArray: Color[] = []; 3 Object.entries(object).forEach(([key, value]) => { 4 if (typeof value === 'string') { 5 const parentKeyName = parentKey === '' ? '' : parentKey + '-'; 6 const keyName = key === 'DEFAULT' ? parentKey : parentKeyName + key; 7 colorArray.push([keyName, value]); 8 } else if (typeof value === 'object') { 9 colorArray = colorArray.concat(getColors(value, key));10 }11 });12 return colorArray;13}
This creates an array of names/values, which I pass to my getGradientStyling to then create a unique class and styling.
Then we add a simple plugin function that calls the required functions.
1plugin(function ({ addUtilities, theme, e }) { 2 const colors = theme('colors') || {}; // get all colors object 3 const colorArray = getColors(colors, ''); // create [key, value] array for each color 4 5 // map through each color 6 const utilities = colorArray.map(([key, value]) => { 7 console.log('ADDING COLORS: ', { key, value, style: getGradientStyling([key, value], e) }); 8 return getGradientStyling([key, value], e); 9 });10 addUtilities(utilities);11});
And voilà, we have a custom Tailwind class that we can configure to work with any color. As demonstrated here with gradient-animate-black.
Feel like cooking this up together?
Whether it's an idea, a refactor, or a new build — tell us briefly about your project. We'll get back to you within 24 hours.
Weiterlesen
15. Jun 2026
Building Responsive Images: The Complete srcset & sizes Guide
Responsive images without hand-waving: how srcset and sizes really work, picture for art direction — and how to generate the variants instead of maintaining them by hand.
06. Jun 2026
Core Web Vitals Are an Image Problem – And How Fairu Solves It
LCP is the Core Web Vital most sites fail — and images are almost always to blame. How Fairu gets them passing, with no pipeline of your own.
10. May 2026
Release 1.109 - Now supports google + github login
Starting today, you can sign in to Fairu with Google or GitHub — no separate password needed anymore.