Tailwind CSS Content Scanning: Configure JIT To Generate Only Used Utilities
Production builds lose Tailwind styles when the JIT compiler cant find template files. This guide covers version-aware content scanning, safelist patterns, and verification steps to keep bundles small and styles intact.
15 Apr 2026, 18:37 UTC

The problem
Your production build outputs almost no Tailwind CSS, even though your templates reference buttons, colors, and layout utilities. The JIT compiler simply didn't find the class names it needed during the scan, so those styles were excluded from the final stylesheet.
Know your Tailwind version
Behavior and configuration syntax are version-sensitive. Tailwind CSS v3 uses an explicit content array in tailwind.config.js, while v4 favors a CSS-first approach with @import tailwindcss and automatic content detection. Run npm list tailwindcss and read the matching major version docs before editing your config.
v3: explicit content array
content: [ './src/**/*.{html,js,ts,jsx,tsx,vue,svelte}', './pages/**/*.{html,js,ts,jsx,tsx}', './components/**/*.{html,js,ts,jsx,tsx}' ]
The glob pattern must cover every template file that contains Tailwind class names. A missing file type or wrong path is the most common cause of styles silently disappearing in production builds.
v4: CSS-first configuration
Tailwind v4 reads template files automatically when @import tailwindcss is used in your main stylesheet, and the framework infers the content scope from the imported CSS and HTML. Explicit content arrays are still supported but often unnecessary if your entry point covers all templates.
Point the content scan at every template
Whether youre on v3 or v4, the scanner relies on glob patterns to locate source files. Use patterns that recurse into directories and enumerate common extensions. A practical pattern looks like:
./src/**/*.{html,js,ts,jsx,tsx,vue,svelte}
This tells the JIT engine to scan every HTML, JavaScript, TypeScript, Vue, React, and Svelte file under src. If your project stores templates elsewhere, add additional patterns or adjust the root path accordingly.
Handle classes that cant be statically discovered
Class detection is static string matching. Utilities built dynamically at runtime, such as text-${color}-500 evaluated from a variable, are not detected by the scanner. The full class name must appear literally in source, or you must list it in the safelist option.
using safelist
safelist: [ 'bg-primary-500', 'text-danger-600' ]
The safelist array accepts explicit class names or regular expressions. It forces the compiler to generate those utilities, at the cost of larger CSS output. Use it sparingly and only for patterns that the scanner cannot resolve.
Build and verify
After configuring the content array or safelist, run a production build to see the result. The command depends on your framework, but for a vanilla Tailwind setup:
npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify
- Search the generated output.css for a utility used in only one template file. It should appear in the output.
- Search for a utility that you never use in templates. It should be absent.
- Compare the file size to the full Tailwind default (tens of kilobytes, not megabytes). A dramatically larger file suggests overly broad scanning or an excessive safelist.
If a deliberately wrong content path is added and the rebuild produces missing styles, youve confirmed that the content scan controls what the JIT compiler generates.
Recover from missing or over-scanned styles
If styles disappear after a config change, temporarily revert the content array or safelist to a known-working state. If you added a broad glob (e.g. scanning node_modules), remove it; build times and CSS size will typically shrink noticeably.
When a dynamic class pattern is required and cannot be expressed literally, add the exact rendered class name or a targeted regex to safelist rather than widening the content scan.
Limitations and practical tips
- Overly broad globs (e.g. scanning node_modules) slow builds significantly and can bloat output.
- Dynamically constructed class strings will not compile even if they look correct in the browser at runtime; this failure only appears after a production build.
- Tailwinds v4 automatic content detection reduces configuration overhead but may not cover custom build steps or non-standard file extensions without explicit patterns.
Run npm list tailwindcss before every config edit, and always verify a production build before deploying.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.