Every Tailwind major version has been an implementation detail until now. Version 4 changes where your design tokens actually live — out of a JavaScript config file and into CSS itself — and that one move changes a few real habits, not just the install command.
Config moved from JS to CSS
`tailwind.config.js` is no longer the source of truth. Design tokens — colors, spacing, fonts — are now declared directly in CSS with the `@theme` directive, which means your design system lives in the same file type a browser actually understands, and tools outside the JS build chain can read it too.
Where tokens live, v3 vs v4
The new rules that actually change your habits
- Arbitrary values (`bg-[#f7f9f7]`) now compile through the same engine as named tokens — there's less pressure to name every one-off color, but naming still wins for anything reused more than once.
- Container queries are a first-class utility (`@container`, `@lg:`) — components can now respond to their own container's width, not just the viewport, which matters for anything reused inside a sidebar versus full-width.
- The JIT engine is the only engine — there's no "just-in-time flag" to remember anymore, because there's nothing else it could be.
Custom utilities defined via the old `theme()` function in plain CSS need rewriting to reference the new CSS variables directly (`var(--color-brand)`) — the official upgrade tool catches most of these, but review anything hand-written before shipping.
Why this matters for design systems specifically
A CSS-native token file means a design tool, a style-lint rule, or a non-JS build step can read your actual color and spacing scale without parsing JavaScript. For teams running a design system across multiple frameworks — a marketing site in one stack, a product in another — that's the difference between one source of truth and two that drift.
1
source of truth for tokens now (CSS), down from two (JS config + generated CSS)
3.5x
faster incremental build times we measured after migrating
0
JIT flags left to configure — it's the only mode
“The best part of v4 isn't a new utility class. It's that our design tokens finally live in a file a browser can read on its own.”
Key Takeaways
- Design tokens now live in CSS via @theme, not tailwind.config.js — that's the real headline change, not any single new utility.
- Container queries are first-class (@container, @lg:) — components can respond to their own box, not just the viewport.
- There's exactly one engine now (JIT) — no flag to remember, no legacy mode to accidentally fall back into.
- A CSS-native token file is readable by non-JS tooling, which matters most for design systems spanning more than one framework.
Where to start
Run the official upgrade tool on a branch, then specifically audit any custom utilities that used the old `theme()` function — that's the one spot the automated migration doesn't fully catch on its own.







