Loading...
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 the maintainer of NiraUI, I talk to developers every day who hit the same frustrating issue: Tailwind CSS classes vanish in production builds when they’re written dynamically.

If your Tailwind classes like bg-{{ color }}-500 or button-{{ type }} ork fine during development but vanish after you build you’re definitely not alone.

This guide explains why it happens and how to fix it using the Tailwind CSS safelist and new Tailwind 4 features.

The Common Mistake: Dynamic Tailwind Classes

Tailwind CSS is a utility-first framework. Normally, you use it like this:

But developers often try to make things “cleaner” or more dynamic:

Or with frameworks and UI libraries like NiraUI:

It looks elegant but there’s one big problem:

Tailwind can’t detect dynamic class names at build time.

Why Dynamic Classes Break in Production

Tailwind scans your project files to see which classes are actually used, and then purges the rest to keep your CSS small.

When you use dynamic class syntax like bg-{{ color }}-500, the scanner doesn’t see the full class name just a variable placeholder. That means Tailwind thinks those styles are unused and removes them from the final build.

That’s why your dynamic styles look fine in dev, but disappear in production.

The Fix: Use the Tailwind CSS Safelist

The safelist tells Tailwind to always include certain classes, even if they aren’t explicitly detected in your code.

Here are three reliable ways to fix disappearing dynamic classes.

1. Use Full Class Names as Variables

Instead of partial strings, store the complete class name in your variable:


let color = 'bg-red-500';

This way, Tailwind sees the exact class name and includes it during the build.

2. Add a Tailwind CSS safelist file

You can create a file that lists all possible class variations — for example,safelist.txt


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.Define a Safelist in tailwind.config.js

If your list is small, you can add it directly to the config:


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

Bonus: Regex Safelist Patterns

Tailwind also supports regex-based safelists, which are great for color variations or loops:


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

This is perfect for components that dynamically render colors or types.

Tailwind 4 Safelist Changes: @source inline()

In Tailwind CSS v4, safelisting is even easier.

You can now define safelisted classes inline in your CSS:


@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 new syntax is cleaner, especially for React, Vue, or Svelte projects where class names are often passed dynamically as props.

Final Thought

Tailwind only generates CSS for class names it can see. Dynamic strings like bg-{{ color }}-500 are invisible unless you safelist them.

To make sure your dynamic Tailwind classes never vanish in production:

  • Use full class variables
  • Add a Tailwind safelist file
  • Or use the Tailwind 4 @source inline directive

These techniques guarantee that your dynamic Tailwind CSS classes stay intact across development and production no more disappearing buttons or color variants.

Further Reading: