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-*becomebg-black/50(modifier syntax)flex-shrink-0becomesshrink-0flex-growbecomesgrowoutline-nonebecomesoutline-hidden(nativeoutline: nonebreaks accessibility)ringnow defaults tocurrentColor(was blue)- Custom utilities go through
@utilitydirective — 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.
Migrate your v3 project to v4, design custom themes and optimise the build Contact us