The Journal

CSS & Layout3 min read

Tailwind CSS v4: Complete Migration Guide and Game-Changing New Features

Tailwind CSS v4 is the biggest release in the framework's history, replacing JavaScript configuration with a CSS-first approach. Here is everything you need to know to migrate your project and take advantage of the powerful new features.

Tailwind v4 changes how the framework is configured. Your tailwind.config.js is gone, and the theme now lives in CSS. The engine is faster and setup is simpler, but a handful of renames will break your build on the first run — so here’s the migration in the order that actually works.

Config lives in CSS

You pull in Tailwind with one import and define your theme inside an @theme block. Every token becomes a real CSS variable, so --color-brand is readable in devtools and at runtime. Your design tokens and your styles finally share one source instead of hiding in a JS file nothing else can see.

app.css
@import "tailwindcss";

@theme {
  --color-brand: oklch(0.68 0.19 264);
  --font-display: "Cal Sans", sans-serif;
  --radius-card: 0.75rem;
}

There’s no content array to maintain either — v4 scans your template files automatically, and you only reach for @source when it can’t find one. Folding that scan into the engine is a big part of why v4 builds noticeably faster.

What actually breaks

The renames are the tripwire. shadow-sm is now shadow-xs, outline-none becomes outline-hidden, and the old @tailwind directives are replaced by a single import. Spacing, ring, and border defaults shifted too, so expect a few pixels to move.

The PostCSS plugin also moved to its own package, @tailwindcss/postcss. Don’t fix any of this by hand — the official codemod does it for you, and it runs cleanest on a branch with nothing else in flight.

Migration order

Run it in this sequence, on a fresh branch you can throw away if it goes sideways. Skipping a step is how people end up debugging a half-migrated build.

  1. Upgrade to Node 20+ and set a modern browser target.
  2. Run npx @tailwindcss/upgrade and read every line of the diff.
  3. Move your theme.extend values into an @theme block.
  4. Delete tailwind.config.js once nothing imports it.

When to wait

Migrate now if you own your styles and target current browsers. The payoff is a faster build and a config you can actually read, and most apps clear that bar today. A theme you can read at a glance is worth the afternoon by itself.

Hold off if a critical plugin hasn’t shipped a v4 build, or you still support older engines. v4 leans on @property and oklch(), which old browsers silently ignore, so check your own analytics before committing.

Frequently asked questions

What changed in Tailwind CSS v4?
Tailwind CSS v4 moves configuration out of JavaScript and into CSS: tailwind.config.js is gone and you define your theme in an @theme block, where every token becomes a real CSS variable. There's also no content array to maintain, since v4 scans template files automatically, which is part of why builds are faster.
How do I migrate a project to Tailwind CSS v4?
Work on a fresh branch and run the official codemod, npx @tailwindcss/upgrade, then read every line of the diff. First upgrade to Node 20+ and set a modern browser target, run the upgrade, move theme.extend values into an @theme block, and delete tailwind.config.js once nothing imports it.
What breaks when upgrading to Tailwind CSS v4, and when should you wait?
The renames break builds: shadow-sm becomes shadow-xs, outline-none becomes outline-hidden, the @tailwind directives are replaced by a single import, and the PostCSS plugin moved to @tailwindcss/postcss. Wait if a critical plugin lacks a v4 build or you support older browsers, since v4 assumes Safari 16.4+, Chrome 111+, and Firefox 128+.