Tailwind CSS v4, released in late 2024, is the biggest rewrite the framework has ever shipped. The new Oxide engine speeds up builds by 10-100x, config moves from JavaScript to CSS, and container queries are supported natively. This article covers every important change and the migration path from v3.

Oxide Engine — Speed

The new engine is Rust + esbuild-based. Instead of v3's PostCSS plugin system, it uses a single-pass CSS parser. For a typical project:

  • Full rebuild: v3 at 900ms becomes v4 at 100ms
  • Incremental build: v3 at 40ms becomes v4 at <5ms
  • Development HMR: effectively instant

CSS-First Config

In v4 the tailwind.config.js is optional — theme definitions now live in CSS via the @theme directive. CSS and native custom properties replace JavaScript config.

/* v4 — full theme in a single CSS file */
@import "tailwindcss";

@theme {
    --color-brand-50:  oklch(97% 0.02 40);
    --color-brand-500: oklch(63% 0.2 40);
    --color-brand-700: oklch(45% 0.18 40);

    --font-serif: 'Instrument Serif', Georgia, serif;
    --font-sans:  'DM Sans', system-ui, sans-serif;

    --breakpoint-3xl: 1920px;

    --animate-fade-in: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

Container Queries

In v3 this required the @tailwindcss/container-queries plugin. V4 brings it into the core — children respond to their container's width rather than the viewport.

<div class="@container">
    <!-- If the card itself is wider than 400px -->
    <div class="grid grid-cols-1 @md:grid-cols-2 @lg:grid-cols-3">
        <!-- Cells layout based on the card width, not the viewport -->
    </div>
</div>

@starting-style and @property

V4 wraps modern CSS natively. @starting-style turns entrance animations into one line, and @property lets you define custom animation values.

<!-- Element slides in when the page loads -->
<div class="starting:opacity-0 starting:translate-y-4 transition-all duration-500">
    Enter animation
</div>

<!-- Popover animation on open -->
<div popover class="opacity-0 open:opacity-100 transition">
    Popover content
</div>

V3 to V4 Migration

# Automatic migration script
npx @tailwindcss/upgrade

# Manual changes:
# 1) Review tailwind.config.js, move the theme into @theme
# 2) Remove tailwindcss from postcss.config.js — v4 no longer requires that plugin
# 3) CSS import
#    v3: @tailwind base; @tailwind components; @tailwind utilities;
#    v4: @import "tailwindcss";

Breaking Changes

  • bg-opacity-*, text-opacity-* become bg-black/50 (modifier syntax)
  • flex-shrink-0 becomes shrink-0
  • flex-grow becomes grow
  • outline-none becomes outline-hidden (native outline: none breaks accessibility)
  • ring now defaults to currentColor (was blue)
  • Custom utilities go through @utility directive — simpler than the old plugin system

Custom Utility — The New Way

/* v3 required a plugin */
/* v4 uses @utility in CSS */
@utility tab-* {
    tab-size: --value(integer);
}

/* Usage */
<pre class="tab-4">Tab size 4</pre>

Performance: Dev-Server Speed

# Benchmark (Tailwind team measurements)
# Full build
v3.4: 378ms  ->  v4.0: 100ms

# Incremental CSS change
v3.4: 44ms   ->  v4.0: 5ms

# Incremental class add (no new CSS)
v3.4: 19ms   ->  v4.0: 2ms

Should You Upgrade?

  • New project: definitely v4
  • Active large project: run the migration script and plan for a one-week sprint
  • Legacy / frozen project: stay on v3 — it will be supported for a long time
  • Plugin-heavy codebase: check v4 compatibility for every critical plugin

Conclusion

Tailwind v4 changed two things: build speed is now a non-issue, and config moved into CSS. Migration is mostly one command, most breaking changes are trivial to fix, and there is no good reason not to pick v4 for a new project in 2026.

Tailwind v4 migration support

Migrate your v3 project to v4, design custom themes and optimise the build Contact us

WhatsApp