Quick Tailwind CSS tip when classes are "mysteriously" not being applied

I had a quick yet interesting bug happening today that I believe is worth to write a small blog post about: a button that had a background color class through Tailwind (specifically bg-purple-600) was being applied correctly in one layout but when dynamically changing it to bg-blue-600 it was rendering ... no background.

The key here is the word "dynamically"

In React, I had something like this:

function MyButton({ iconColor }) {
  return (
    <button className=`bg-${iconColor}-600 hover:bg-{iconColor}-700`>
      My button label
    </button>
  )
}

The iconColor prop was handled elsewhere and stored as "purple" or "blue". The problem here is that Tailwind scans your code to only load the CSS classes that are being used without running any code. From the Tailwind docs:

"The way Tailwind scans your source code for classes is intentionally very simple — we don’t actually parse or execute any of your code in the language it’s written in, we just use regular expressions to extract every string that could possibly be a class name." — Tailwind Docs

This means that unless both purple and blue have been referenced elsewhere as a literal "bg-purple-600" or "bg-blue-600", it won't be added in the CSS!

The solution

Despite some people recommending adding a hidden div with the dynamic class names that you are using, and although the documentation says that it is a best practice to use full qualified names instead of class name interpolation, there's another way for truly dynamic values: safelist.

In the tailwind.config.js file, you can add a key in the configuration object called safelist and name the classes that should be added. It goes without saying but as a reminder, hover classes and "normal" classes are different! So bg-blue-600 is different than hover:bg-blue-600 so add both if you are using both dynamically.

Here's more info about safe listing classes: https://tailwindcss.com/docs/content-configuration#safelisting-classes.