DEV3 Technologies home

DEV3 Developer Forum

Why don't my dynamic Tailwind classes like `bg-${color}-500` work?

dev3 ·

I build class names from props, for example className={bg-${color}-500 text-${size}}. In dev some work and in production they vanish. Why, and how do I handle dynamic styles?

#tailwind#dynamic-classes#build

0

1 reply

dev3 · Accepted answer

Cause

Tailwind does not execute your code. It scans source files as plain text for complete class names and generates only those. bg-${color}-500 contains no complete class, so no CSS is created. It appears to work in dev only if the same class happens to exist elsewhere in your files.

Fix 1: map to complete class names

const colors = {
  red:   'bg-red-500 text-white',
  green: 'bg-green-500 text-white',
  blue:  'bg-blue-500 text-white',
} as const

type Color = keyof typeof colors

export function Badge({ color }: { color: Color }) {
  return <span className={`rounded px-2 py-1 ${colors[color]}`}>...</span>
}

Tailwind sees every full string in the lookup, so all are generated.

Fix 2: variants helper

class-variance-authority (cva) or tailwind-variants formalise the lookup pattern for components with size, color and state variants.

Fix 3: safelist when classes come from a database or CMS

Tailwind 4.1 and newer:

@source inline("bg-{red,green,blue}-500");

This forces generation of those classes. On v3 use safelist in tailwind.config.js. You can also point @source "../node_modules/some-ui-lib"; at files Tailwind does not scan automatically (v4 respects .gitignore, so ignored paths are skipped).

Fix 4: use CSS variables for values

<div style={{ '--accent': color } as React.CSSProperties}
     className="bg-(--accent)" />

The class is static, the value is dynamic. Same for widths and heights computed at runtime.

Pitfalls

  • Ternaries are fine when both branches are full strings: isOn ? 'bg-green-500' : 'bg-gray-300'.
  • Do not concatenate fragments like 'bg-' + name.
0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.