English
no-dynamic-classes
oxlint rule that reports Tailwind CSS classes built at runtime, like bg-${color}-500, which Tailwind never sees written out and so generates no CSS for.
At a glance
| Autofix | Editor suggestions | Design system | Options |
|---|---|---|---|
| No | No | Optional — used when entryPoint is set | entryPoint |
What this rule does
Tailwind generates CSS for the class names it finds written out in your source files. A class put together at runtime — `bg-${color}-500`, `text-${size}`, `w-[${width}px]` — never appears in full anywhere, so Tailwind emits nothing for it and the element silently goes unstyled. It works in development only if the same class happens to be written out somewhere else.
The rule reports each such class once, when the text glued to a ${} — or to a + operand, "bg-" + color — starts with a Tailwind utility (bg-, grid-cols-, -mt-, w-[) or a variant (hover:, md:, data-). A whole class or list coming from a variable (`${base} p-4`, "p-4 " + extra) is fine, and so is text that isn't Tailwind's (`icon-${name}`, `${a}-${b}`). A class split over two strings ("bg-" + "red-500") is reported too: Tailwind reads each string on its own. There is no autofix: the fix is to write out every class the value can map to.
DS-optional. With an entryPoint, your project's own utilities and variants count too (a @theme namespace such as bar-*); without one, Tailwind's built-in utility and variant roots are used.
What it doesn't see: a variant chosen at runtime after the static text (`${breakpoint}:flex`).
Options
entryPoint
string, optional. Per-rule override of settings.tailwindcss.entryPoint, used to read your project's utilities and variants.
Examples
✗ Incorrect
tsx
<div className={`bg-${color}-500 p-2`} />
<div className={`text-${size} font-bold`} />
<div className={`w-[${width}px]`} />
<div className={`hover:${hoverClass}`} />
<div className={cn(`p-${padding}`)} />
<div className={"text-" + tone} />✓ Correct
tsx
// Write out every class the value can map to
const bgByColor = { red: 'bg-red-500', blue: 'bg-blue-500' } as const
<div className={`${bgByColor[color]} p-2`} />
// Pick between full class names
<div className={cn(active ? 'bg-blue-500' : 'bg-gray-500')} />
// A value that really is dynamic: a CSS variable, set inline
<div className="w-(--width)" style={{ '--width': `${width}px` }} />Interactions with other rules
no-unknown-classesignores the glued fragments (bg-,-500) — they aren't classes, and this rule is the one that reports them.no-arbitrary-value: the CSS-variable fix above is an arbitrary value; allow it withallowVariables: 'runtime'.
When to disable it
- Your classes are safelisted (
@source inline(…)), so Tailwind generates them whether or not they appear in the source. Disable the rule for those files, or for the project if everything is safelisted.