The most common mistake when using Tailwind CSS (and how to fix it)

The most common mistake when using Tailwind CSS (and how to fix it)

As a maintainer of Nira UI, I interact with developers daily on GitHub issues and discussions. One of the most common mistakes I see when using Tailwind CSS is surprisingly simple to avoid—but it trips up even experienced developers.

If you’ve struggled with dynamic Tailwind class names not working in production, this guide is for you.

The Mistake

Tailwind CSS is designed to be utility-first. You typically use it like this:

Tailwind CSS is designed to be utility-first. You typically use it like this:

Or with Nira UI buttons:

This works perfectly in development but breaks in production builds.

Why Dynamic Classes Break in Production

Tailwind CSS scans your HTML and JavaScript files to detect class names and generate CSS.

  • When you write bg-{{ color }}-500 ,Tailwind cannot detect the actual class names (bg-red-500, bg-green-500) because they are dynamically generated.
  • As a result, those CSS classes are not included in the final production build.

How to Fix It

There are three recommended ways to handle dynamic Tailwind CSS classes properly:

1. Use Full Class Names as Variables

Instead of embedding partial class names, store the complete class name in a variable:


let color = 'bg-red-500';

This ensures Tailwind can detect the exact class name and include it in the build.

2. Add a Safelist File

Create a safelist.txt file containing all dynamic classes:


bg-red-500
bg-green-500
bg-blue-500

Then include it in your tailwind.config.js:


module.exports = {
  content: ["./path/safelist.txt", "./pages/**/*.{html,js}", "./components/**/*.{html,js}"],
  // ...
}

3. Use the Safelist Option in Tailwind Config

You can also define a safelist directly in tailwind.config.js:


module.exports = {
  content: ["./pages/**/*.{html,js}", "./components/**/*.{html,js}"],
  safelist: [
    "bg-red-500",
    "bg-green-500",
    "bg-blue-500",
  ],
}

Advanced: Regex Patterns


module.exports = {
  content: ["./pages/**/*.{html,js}", "./components/**/*.{html,js}"],
  safelist: [
    "bg-teal-700",
    {
      pattern: /bg-(red|green|blue)-(400|500|600)/,
    },
  ],
}

This is ideal for dynamic class names generated in loops or components.

Tailwind v4 Migration Notes

Tailwind v4 changes how you safelist classes. The safelist option is no longer the primary method. Instead, use the new @source inline(...) directive:


@import "tailwindcss"; 
@source inline("bg-red-500", "bg-green-500", "bg-blue-500"); 
/* With brace expansion */
@source inline("{hover:,}bg-{red,green,blue}-500");

This tells Tailwind to always include those classes in your CSS, even if they don’t appear literally in your HTML or JSX.

Final Thought

  • Tailwind only generates CSS for class names it can detect. Dynamic strings like bg-{{ color }}-500 are invisible to Tailwind.
  • Development may work due to cached styles, but production builds require explicit classes.
  • Use variables, safelist files, or the safelist option to ensure your dynamic classes work consistently.

Further Reading: