Tailwind CSS JIT vs Legacy Mode: A Decision Guide for Build Speed and CSS Size
Choose between Tailwind CSS JIT and legacy mode by weighing build speed, CSS size, dynamic class handling, and PostCSS compatibility. Includes a config example and validation steps.
08 Feb 2026, 23:44 UTC

If your Tailwind build takes seconds to rebuild and ships hundreds of kilobytes of CSS, you are likely running in legacy mode. The choice between Just-In-Time (JIT) compilation and the legacy generate-all approach determines build speed, production bundle size, and how safely you can use dynamically constructed class names. On Tailwind v3 and later, JIT is the default and the only mode; the decision is most relevant if you maintain a v2.x project or plan an upgrade.
The decision and its constraints
Four constraints usually drive this choice: iteration speed during development, the size of the CSS shipped to production, whether class names are generated at runtime, and compatibility with your existing PostCSS pipeline. JIT optimizes the first two but tightens the third; legacy mode relaxes the third at the cost of the first two.
JIT vs legacy mode at a glance
| Constraint | JIT mode | Legacy mode |
|---|---|---|
| Build time | Fast incremental rebuilds | Slower full rebuilds |
| Production CSS size | Only detected utilities | All possible utilities |
| Development workflow | Instant updates, no purge step | Manual purge or large CSS |
| Dynamic class names | Requires accurate content globs or safelist | All utilities present by default |
| Pipeline requirements | PostCSS 8+; older setups may need upgrading | Any PostCSS setup |
| v3+ availability | Default and only mode | Not available |
Trade-offs in practice
JIT scans your source files for class names and emits only the CSS that matches. This keeps stylesheets small and rebuilds fast, but it introduces a failure mode: if a class name is assembled at runtime—for example `text-${color}-500`—the scanner never sees the literal string, so the utility is missing from the output. Legacy mode generates every utility up front, so those dynamic names work without extra configuration, but the stylesheet is large and slow to rebuild. In production, legacy mode depends on a purge step to remove unused CSS; JIT does not need purge because it never generates unused rules in the first place.
Implementation: enabling JIT with explicit content paths
For a Tailwind v2.x project, enable JIT explicitly and define content paths. In v3+, the mode option is unnecessary because JIT is always on, but content is required.
// tailwind.config.js (Tailwind v2.x)
module.exports = {
mode: 'jit',
content: [
'./src/**/*.{html,js,jsx,ts,tsx,vue}',
'./public/index.html',
'./src/components/**/*.{js,jsx,ts,tsx}'
],
theme: {
extend: {},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
};
Run your development server from the project root—for example npm run dev or vite—and edit a source file. You should see CSS updates without a full rebuild. For production, run npm run build in the project root; the emitted stylesheet should contain only the utilities your content globs matched.
Validation: checking output and dynamic classes
- Measure the stylesheet. After a production build, locate the generated CSS file (commonly under
dist/orbuild/, depending on your bundler). With JIT active, expect a file measured in kilobytes; legacy mode typically produces hundreds of kilobytes before purge. - Grep for a known utility. Search the built CSS for a class you use, such as
flexortext-center. Then search for an unused utility likeskew-x-12. If the used class is present and the unused one is absent, scanning and emission are working correctly. - Toggle a dynamic class. In browser devtools, add a class to an element via the Elements panel or a small script. If the style applies immediately, JIT is serving the utility on demand. If the style is missing, the class was not covered by your content globs.
- Safelist missing classes. If a runtime-generated class is absent, add the literal string to your safelist configuration and rebuild to confirm it appears in the output.
Limitations and rollback
Runtime string concatenation is the most common cause of missing styles under JIT. Some third-party plugins written for v2 assumed the full utility set was available; verify plugin compatibility when switching modes. Aggressive CSS minifiers can also strip custom properties generated by Tailwind, so check your minifier settings if theme variables disappear. Legacy mode without purge sends the entire utility catalog to the browser, which hurts performance on slow connections.
If you enabled JIT in a v2.x project and need to revert, remove the mode: 'jit' line and restore your previous purge configuration. In v3+, there is no legacy fallback; if you must keep dynamic class names, use the safelist option instead.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.