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
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
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
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
isOn ? 'bg-green-500' : 'bg-gray-300'.'bg-' + name.