Skip to content

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 ​

AutofixEditor suggestionsDesign systemOptions
NoNoOptional — used when entryPoint is setentryPoint

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-classes ignores 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 with allowVariables: '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.

Released under the MIT License.