Dynamic utility classes excluded from Tailwind CSS v3 JIT output
0 reputation · 18 Dec 2024, 16:42 UTC
0 reputation · 18 Dec 2024, 16:42 UTC
Tailwind CSS v3 runs the Just-in-Time engine by default and only emits utilities that appear as literal strings inside configured content paths. Class names assembled at runtime with template literals or concatenation, such as text-${color}-500, are invisible to that static scan. As a result, styles that work during development can disappear from the production build.
The goal is to keep dynamically generated utilities available without guessing every possible variant. The safelist setting can preserve classes the scanner cannot discover, but a large safelist may increase output size and build time. This question assumes Tailwind CSS v3.x; behavior in later major versions may differ.
What is the recommended boundary between safelisting dynamic patterns and refactoring them into complete literal class strings? Are there configuration options that safely cover generated utility names without listing each variant? What criteria should determine whether a dynamic utility is safelisted versus rewritten as a complete literal?
Tailwind CSS v3 JIT emits only utilities that appear as literal strings in the configured content paths. Runtime assembled names like text-${color}-500 are invisible to the static scan, so they are missing from production CSS.
JIT scanning is literal-string based. The safelist option can preserve utilities the scanner cannot find. A safelist entry can be a literal class string or a pattern object with a regex. Patterns can be scoped with variants and separator to cover responsive and state variants.
A pattern that is too broad inflates bundle size and can include unintended utilities. A pattern that is too narrow misses dynamically generated classes. Production builds must be inspected, because dev builds can mask missing utilities.
Refactor to complete literal class strings when the set is small, predictable, and statically knowable. Use a safelist when the set is dynamic or large.
In tailwind.config.js:
module.exports = {
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
safelist: [
// literal fallback for known values
'text-red-500',
'text-blue-500',
// pattern for dynamic color utilities
{
pattern: /^text-(red|blue|green|amber)-500$/,
variants: ['sm','md','hover','focus'],
separator: '-'
}
]
}Use variants to explicitly cover responsive and state forms you need. Use a tight regex with an allowlist of values instead of text-.*-500.
sm:, hover: etc.? Patterns must include those variants or you must refactor.One diagnostic detail that changes the recommendation: do you need responsive and state variants for the dynamic utilities, e.g., sm:text-${color}-500 or hover:text-${color}-500? If yes, the safelist pattern must include those variants or refactoring to literals is safer.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.