Contents

Tailwind v4: Oxide Rust Engine, 182x Incremental Builds, CSS Config

Tailwind CSS v4 is a ground-up rewrite. The JavaScript-based PostCSS plugin is gone. In its place is a Rust-powered engine called Oxide. Configuration moves from tailwind.config.js into CSS-native @theme directives. Full builds run up to 5x faster, and incremental builds over 100x faster. The entry point is now a single @import "tailwindcss" line instead of three @tailwind directives. Most v3 projects can migrate in under an hour with the official @tailwindcss/upgrade codemod. Still, knowing what changed, and why, prevents surprises during the move.

Tailwind CSS v4.0 shipped on January 22, 2025. Since then, v4.1 and v4.2 have followed. They added a webpack plugin, new color palettes, and logical property utilities. The core architecture, though, was set in v4.0. It remains the foundation for everything that came after.

Tailwind CSS v4.0 release announcement card
The official Tailwind CSS v4.0 announcement from January 2025

What the Oxide Engine Changes Under the Hood

The biggest change in Tailwind v4 is invisible to your markup. Oxide is a Rust-compiled CSS engine. It handles content detection, CSS generation, and optimization in a single pass. It replaces three separate JavaScript parts from v3: the PostCSS plugin, the JIT compiler, and the content scanner.

Tailwind CSS v4 announcement showing the new version release with Oxide engine
Tailwind CSS v4 — powered by the new Rust-based Oxide engine
Image: Tailwind CSS

The speed gain is measurable. The Tailwind team ran benchmarks against their own Catalyst project:

Metricv3.4v4.0Improvement
Full build378ms100ms3.78x
Incremental rebuild (new CSS)44ms5ms8.8x
Incremental rebuild (no new CSS)35ms192us182x

That last row is the one you feel most in daily work. Say you are writing markup and reusing classes you already used, like flex, col-span-2, or font-bold. The incremental build then finishes in microseconds. HMR becomes near-instant even on large codebases. Developers on production projects report build times dropping from 12 seconds to 1.2 seconds. Hot module replacement goes from 500ms to under 100ms.

The speed comes from native CSS parsing. Oxide reads and writes CSS without converting to and from JavaScript ASTs. That cuts out serialization overhead. Parse speeds run about twice as fast as tools like SWC, and far faster than the old PostCSS build.

Oxide also changes how Tailwind ties into your build tool. In v3, Tailwind was only a PostCSS plugin. In v4, you get three options:

  • The Vite plugin (@tailwindcss/vite) is the recommended path. It offers the tightest integration and best speed.
  • The PostCSS plugin (@tailwindcss/postcss) keeps backward compatibility with existing PostCSS pipelines.
  • The standalone CLI (npx @tailwindcss/cli -i input.css -o output.css) works for projects with no JavaScript bundler. That includes Hugo sites and other static site generators.

Automatic content detection is another win from the new engine. Oxide scans your project for source files on its own. It picks up HTML, JSX, TSX, Vue, Svelte, PHP, and more. You no longer need a content array in your config. It uses heuristics and your .gitignore to pick which files to scan. That removes the single most common v3 misconfiguration.

The tailwindcss npm package in v4 ships with the Rust binary for your platform via optional dependencies. Total install size is around 15 MB. That compares to v3’s roughly 45 MB with all its JavaScript dependencies.

Tailwind CSS GitHub repository showing the project description and stats
The tailwindlabs/tailwindcss repository on GitHub

CSS-Native Configuration with @theme and @variant

The biggest developer-facing change is that configuration moves from JavaScript into your CSS. The shift changes how you define, reference, and override design tokens at every level of your project.

The entry point changes first. Replace the three v3 directives:

/* v3 - remove this */
@tailwind base;
@tailwind components;
@tailwind utilities;

With a single import:

/* v4 */
@import "tailwindcss";

This one line imports the whole framework: preflight, utilities, and your theme.

The @theme directive replaces the theme.extend object from tailwind.config.js. Instead of JavaScript:

// v3 tailwind.config.js - no longer needed
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: '#3b82f6',
      },
      fontFamily: {
        sans: ['Inter', 'sans-serif'],
      },
    },
  },
}

You write CSS:

/* v4 - directly in your CSS file */
@theme {
  --color-brand: #3b82f6;
  --font-sans: "Inter", sans-serif;
  --breakpoint-3xl: 1920px;
}

Every theme value in v4 is a CSS custom property. So you can reference it anywhere with var(--color-brand) and change it at runtime. In v3, the theme() function only worked at build time. Now your design tokens are live CSS variables. Any stylesheet, JavaScript, or browser devtool can read them.

Custom variants replace the addVariant plugin API:

@variant hocus (&:hover, &:focus);

This makes a hocus: modifier you can use on any utility class. Custom utilities replace the addUtilities API:

@utility tab-4 {
  tab-size: 4;
}

This generates tab-4 as a utility with full responsive and state variant support.

Plugins also move into CSS. Instead of require() calls in your config file, you import them straight in:

@plugin "tailwindcss-animate";

The plugin format changed between v3 and v4, so check each plugin’s docs for compatibility. The official first-party plugins all have v4-compatible versions: @tailwindcss/typography, @tailwindcss/forms, and @tailwindcss/aspect-ratio.

Breaking Changes and Renamed Utilities

v4 keeps most of v3’s utility class names. Still, several were renamed, removed, or changed behavior. The @tailwindcss/upgrade codemod handles roughly 90% of these on its own. You should still know what to look for during code review.

The most widespread breaking change is the gradient utility rename. All bg-gradient-to-* utilities become bg-linear-to-*. That follows CSS-native linear-gradient naming. It affects nearly every project that uses Tailwind gradient backgrounds. The rename also unlocks new tricks: you can now use angle-based gradients like bg-linear-45 for a 45-degree gradient.

Several other utilities have been removed or renamed:

v3 Utilityv4 Replacement
decoration-clone / decoration-slicebox-decoration-clone / box-decoration-slice
overflow-ellipsistext-ellipsis
flex-grow-* / flex-shrink-*grow-* / shrink-*
bg-opacity-*, text-opacity-*Slash syntax: bg-blue-500/75
transform (prefix class)Removed - transforms apply automatically

The default border color changed. In v3, border applied border-color: currentColor. In v4, the default is --color-gray-200, a light gray. So any border that relied on the text color will look different. Check your UI after migration for unexpected color shifts.

The ring utility now defaults to a 1px ring instead of 3px. If you relied on the old default, use ring-3 to get the same look.

Gradient color blending also changed. v4 blends gradients in the oklab color space by default. That gives smoother, more even transitions between colors. Gradients that looked fine in v3 may shift slightly. The via color stop behavior changed too, so test gradient-heavy UIs with care.

Container queries no longer need a plugin. Built-in support replaces the v3 @tailwindcss/container-queries plugin. The new @min-* and @max-* variants use a fresh syntax.

Step-by-Step Migration from Tailwind v3 to v4

Follow these steps in order. Create a new branch before you start, so you can review all changes in a single diff.

Start by running the upgrade codemod:

npx @tailwindcss/upgrade

The tool scans your project and does four jobs. It updates class names in your HTML, JSX, and TSX files. It converts tailwind.config.js to @theme directives in your CSS. It updates package.json dependencies. It needs Node.js 20 or higher. Review all changes before you commit. The tool handles roughly 90% of mechanical changes, but it may miss edge cases in dynamically built class names.

Next, update your build tool integration. The path depends on your stack. If you use Vite, swap the tailwindcss and autoprefixer PostCSS plugins for @tailwindcss/vite in vite.config.ts. This is the recommended setup for new projects. For Next.js, update to version 15 or higher, which has built-in Tailwind v4 support. Webpack users can use the @tailwindcss/webpack plugin, shipped since v4.2. If you run Hugo or another non-JS static site generator, switch to @tailwindcss/cli. Run npx @tailwindcss/cli -i input.css -o output.css as part of your build. For tips on getting more speed out of Hugo’s asset pipeline next to the Tailwind CLI, see Hugo build performance optimization .

Then replace the CSS entry point. In your main CSS file, change the three @tailwind directives to @import "tailwindcss". If you used @tailwind base; @tailwind components; @tailwind utilities;, swap all three for the single import.

Migrate tailwind.config.js to @theme next. The codemod handles most of this, but verify the output manually:

  • theme.extend.colors becomes @theme { --color-*: ... }
  • theme.extend.fontFamily becomes @theme { --font-*: ... }
  • Custom screens and breakpoints become @theme { --breakpoint-*: ... }
  • Delete tailwind.config.js when done

Update your plugins next. Replace require() calls in your old config with @plugin imports in CSS. Check each plugin’s GitHub repository for v4 support:

  • DaisyUI needs an upgrade to v5. DaisyUI v4 does not work with Tailwind v4.
  • Shadcn/ui has been fully compatible since January 2026. Its CLI generates v4-ready components on its own.
  • Flowbite v3 includes full Tailwind v4 support.

Finally, run visual regression testing. Compare screenshots of key pages before and after migration. Percy, Playwright visual comparison, or even manual side-by-side screenshots all work. Most visual regressions trace back to the border color default change and the ring width change.

New Features Worth Adopting After Migration

Beyond fixing what broke, v4 adds features that improve your workflow and CSS output. Several are worth picking up right away.

All theme values are now CSS custom properties. So you can set up dark mode by redefining variables directly :

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #0a0a0a;
    --color-text: #e5e5e5;
  }
}

This works next to or instead of Tailwind’s dark: variant. It gives you more control over theme switching.

Container queries are now first-party . You can style components by their container’s width instead of the viewport. Use @sm:text-lg and @lg:grid-cols-3 as responsive modifiers. No plugin, no config.

The @starting-style variant is new. CSS @starting-style lets you animate elements from display: none. That means pure-CSS modal and dropdown open animations with no JavaScript. Tailwind v4 exposes it through a variant.

v4 also adds @property support. You can define custom CSS properties with types and initial values. That lets you smoothly transition CSS variables that you could not animate before:

@property --gradient-start {
  syntax: "<color>";
  inherits: false;
  initial-value: blue;
}

Arbitrary value syntax got a small but welcome fix: bg-[--my-var] now works with no var() wrapping. Tailwind spots CSS variable references on its own.

3D transform utilities like rotate-x-45, rotate-y-90, and perspective-500 are built in. You no longer need arbitrary values or custom plugins for them.

The gradient system grew too. Beyond the rename from bg-gradient to bg-linear, v4 adds radial gradients (bg-radial), conic gradients (bg-conic), and blending modes. Before, you could only get these through arbitrary values or third-party plugins.

Common Migration Pitfalls

A few issues come up again and again in real-world migrations. The codemod does not catch them on its own.

Dynamic class names are the most common blind spot. Say you build class names through string joining or template literals, like bg-${color}-500. The upgrade tool cannot rewrite these. Search your codebase for patterns like this and fix them by hand. The gradient rename, bg-gradient to bg-linear, is the most frequent case.

Third-party component libraries need a look too. If you use a library that ships pre-built Tailwind classes, check whether it has a v4-ready release before you upgrade. Upgrading Tailwind without upgrading the library can break styles.

PostCSS config conflicts trip people up when the pipeline includes other plugins that process Tailwind’s output. The new Oxide engine may behave differently with them. The Vite plugin path avoids most of this, since it skips PostCSS entirely.

CSS specificity has changed. Tailwind v4 uses native CSS cascade layers (@layer theme, base, components, utilities). If you have custom CSS that leaned on v3’s specificity behavior, the layer boundaries may make your overrides act differently. Use the @layer directive in your custom CSS to put rules in the correct layer.

Check your Node.js version before you start. The upgrade tool and v4 itself need Node.js 20 or higher. If your CI pipeline or dev environment runs an older version, update it first.

For most projects, the codemod does the mechanical work. The rest is visual testing plus fixing edge cases that tooling cannot spot. Budget an hour or two for a typical project. Allow longer if you have many custom plugins or a lot of dynamic class building. The build speed gain alone makes the migration worth doing soon.