Rob Zolkos avatar

Rob Zolkos

November 30, 2024

Beware Tailwind Color Changes

Let’s talk about the humble HTML button. Let’s imagine you have a beautiful button that you styled in the classic green style made famous by all the scientific research that showed that a green button converts better.

You code it like this (probably using bootstrap):

  <button class="btn btn-success">Buy Now</button>

And render like this - the green is hex #28a745:

Then Tailwind comes along and you decide to use it because it’s the new hotness. You convert your button to use Tailwind classes (along with its rad color pallette) and it looks like this:

  <button class="bg-green-500 text-white font-medium py-2 px-4 rounded">Buy Now</button>

Then Tailwind v2 is released and they update the color palette. The color value of the green-500 class you have been using was #48BB78 but now its #10B981. So now the button looks like this:

Then Tailwind v3 is released and they again update to the color palette. The color value of the green-500 class is now #22c55e. So now the button looks like this:

And soon, Tailwind 4 will be released (currently in Beta) and the colors have changed again (this time to a modern P3 color palette). So green-500 is now oklch(0.723 0.219 149.579) and the button looks like this:

Each of these buttons background color is different yet was using the same Tailwind class for the background color.

You have lost control of your colors

Whilst Adam and the Tailwind team are doing a great job of keeping the framework up to date and modern, the fact that the color values are subtly changing with each release could be problem for your users and the consistency of your application. If you have a large codebase and you are using Tailwind, you will have to update all your color values with each release. This is a problem. If you are not using button components and have *-green-500 littered throughout your codebase then this will bite you.

What can you do?

With Tailwind 4, color values are now set as CSS variables. You can see in the Tailwind source where colors are set. This means it is super easy to set your own semantic color values and use them in your application.

What do I mean by semantic color values? I mean that you should name your colors based on their use in your application. For example, you could have a primary color, a secondary color, a success and danger color, etc. You can then use these color values in your application and if Tailwind changes the color values, you only have to update your color values in one place.

Here is an example of how you could set your own color values:

@theme {
  --color-success: oklch(0.723 0.219 149.579);
  /* Tailwind 4 green-500, but will withstand Tailwind version changes */
}

Now you can style a button like this:

  <button class="bg-success text-white font-medium py-2 px-4 rounded">Buy Now</button>

Now if Tailwind changes the color values, your buttons will remain consistent and always use the value you set.

I prefer to name the colors myself rather than redefining what green-500 means. I could have made the value of green-500 like this:

@theme {
  --color-green-500: oklch(0.723 0.219 149.579);
}

Now anytime Tailwind changes the value of green-500, my green-500 will remain the same. The issue is that when the client comes along and wants the buttons to now be red, then I would need to make those changes in a number of areas. Get’s messy. With semantic naming I can just change the value of --color-success and all my buttons will change.

So why use the Tailwind color classes at all?

The Tailwind color classes are great for prototyping and getting up and running quickly. They are also great for small projects where you don’t have to worry about the color values changing. But if you are building a large application, you should consider setting your own color values (even if they are copies of the ones in the version of Tailwind you are using).

I recommend you abstract the color values for common elements like the buttons, links, body copy and headings. This way you can change the color values in one place and have the changes reflected throughout your application.