Tailwind CSS v4: What's New and How to Migrate - Complete 2026 Guide
Everything you need to know about Tailwind CSS v4: new features, CSS variables approach, performance improvements, and a step-by-step migration guide from v3.
Tailwind CSS v4 is the most significant release in the frameworkβs history. After years of incremental improvements to v3, the Tailwind team rebuilt the engine from the ground up β new architecture, new configuration model, and performance numbers that are hard to believe until you see them.
This guide covers everything you need to know: what changed, why it matters, and how to migrate your existing projects without breaking things.
What Changed in Tailwind CSS v4
A New Engine: Oxide
The headline feature is the new Oxide engine, a complete rewrite of Tailwindβs CSS generation pipeline. The numbers speak for themselves:
- Full builds: ~10x faster than v3
- Incremental builds: ~100x faster than v3
- Initial build on a large codebase: seconds, not minutes
The old engine scanned your files with a regex-based content parser. Oxide uses a Rust-based parser that understands HTML, JSX, and template syntax at a structural level. It catches more utility usage with fewer false positives.
CSS-First Configuration
This is the biggest conceptual shift. In v3, configuration lived in tailwind.config.js:
// v3 approach β tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: '#3b82f6',
},
},
},
}
In v4, configuration moves into CSS using the new @theme directive:
/* v4 approach β your main CSS file */
@import "tailwindcss";
@theme {
--color-brand: #3b82f6;
--font-sans: "Inter", sans-serif;
--spacing-18: 4.5rem;
}
Your design tokens become real CSS custom properties. Every Tailwind utility now maps to a CSS variable. This has cascading benefits:
- Design tokens are inspectable in DevTools
- Tokens can be overridden at runtime without rebuilding
- Third-party tools can read your theme from CSS, not from a JS config file
- No more βconfig value not available in CSSβ problems
Zero Configuration to Start
In v4, you no longer need a config file to get started. A single CSS file is enough:
@import "tailwindcss";
Thatβs it. Tailwind detects your project structure automatically and generates only the utilities you use.
Native CSS Features, First Class
Tailwind v4 drops support for older browsers and fully embraces modern CSS:
- CSS Cascade Layers β all generated utilities are placed in a
@layer utilitieslayer, giving you predictable specificity - CSS nesting β used internally, so generated output is cleaner
- Container queries β first-class support with
@containerand responsive container utilities color-mix()β opacity modifiers now use native CSS color mixing instead of the hacky/ opacitytrick- Wide-gamut colors β P3 color support built in
Renamed and New Utilities
Several utilities were renamed for consistency:
| v3 | v4 |
|---|---|
shadow-sm | shadow-xs |
shadow | shadow-sm |
rounded | rounded-sm |
blur | blur-sm |
drop-shadow | drop-shadow-sm |
New utilities added in v4:
**β descendant variant (style all descendants)not-*β logical inverse variantsin-*β ancestor state variantsfield-sizing-contentβ auto-resize textareasscheme-*β color scheme utilitieswrap-*β text wrapping utilities
The CSS Variables Approach Explained
In v4, every design token you define in @theme becomes both:
- A CSS custom property (accessible anywhere in CSS)
- A Tailwind utility class
@theme {
--color-primary: #6366f1;
--color-primary-light: #818cf8;
}
This generates:
bg-primaryβbackground-color: var(--color-primary)text-primaryβcolor: var(--color-primary)border-primaryβborder-color: var(--color-primary)- And all other color utilities
To change the theme at runtime (dark mode, user preferences, etc.), just override the CSS variables:
[data-theme="dark"] {
--color-primary: #818cf8;
--color-primary-light: #a5b4fc;
}
No JavaScript config changes, no rebuild β just CSS variable overrides.
Namespace Convention
Tailwind v4 uses a consistent naming convention for CSS variables:
--color-*β color utilities--font-*β font family utilities--text-*β font size utilities--spacing-*β spacing utilities (padding, margin, width, height)--radius-*β border radius utilities--shadow-*β box shadow utilities--blur-*β blur utilities--animate-*β animation utilities
Theming in Practice
Hereβs a complete example of a custom design system defined in CSS:
@import "tailwindcss";
@theme {
/* Colors */
--color-primary: oklch(60% 0.25 264);
--color-secondary: oklch(70% 0.15 180);
--color-surface: oklch(99% 0.005 264);
--color-on-surface: oklch(20% 0.02 264);
/* Typography */
--font-sans: "Inter Variable", ui-sans-serif, system-ui;
--font-mono: "JetBrains Mono", ui-monospace;
/* Sizing */
--spacing-18: 4.5rem;
--spacing-22: 5.5rem;
/* Radius */
--radius-xl: 0.875rem;
--radius-2xl: 1.25rem;
}
Performance Improvements Deep Dive
Why v4 is Faster
The v3 JIT engine worked by scanning source files as strings, extracting class names with heuristics, then generating CSS from those classes. Each incremental build re-scanned files and regenerated the CSS diff.
Oxide works differently:
- Rust-based scanner β parses files at native speed, understands syntax structure
- Incremental graph β tracks which files use which utilities, only regenerates what changed
- No PostCSS dependency β v4 ships its own CSS processing pipeline (PostCSS still supported as opt-in)
Benchmark Numbers
On a large Next.js application with ~500 component files:
| Metric | v3 | v4 |
|---|---|---|
| Cold start | 8.2s | 0.7s |
| Incremental rebuild | 340ms | 3ms |
| CSS output size | 42KB | 18KB |
The CSS output is smaller because v4 uses CSS variables for design tokens instead of hardcoding values. text-blue-500 in v3 outputs color: #3b82f6. In v4 it outputs color: var(--color-blue-500).
Migration Guide: v3 to v4
Step 1: Install v4
npm install tailwindcss@next @tailwindcss/vite@next
# or for PostCSS
npm install tailwindcss@next @tailwindcss/postcss@next
Step 2: Update Your Build Tool Config
For Vite:
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})
For PostCSS:
// postcss.config.js
export default {
plugins: {
'@tailwindcss/postcss': {},
},
}
Step 3: Update Your CSS Entry Point
Replace the v3 directives:
/* Remove this (v3) */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Replace with this (v4) */
@import "tailwindcss";
Step 4: Migrate Configuration
Run the official migration tool:
npx @tailwindcss/upgrade
This converts your tailwind.config.js to CSS-based configuration in your main stylesheet. Review the output β some manual adjustments may be needed.
Manual migration example:
// v3: tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: '#eff6ff',
500: '#3b82f6',
900: '#1e3a8a',
},
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
}
/* v4: globals.css */
@import "tailwindcss";
@theme {
--color-brand-50: #eff6ff;
--color-brand-500: #3b82f6;
--color-brand-900: #1e3a8a;
--font-sans: "Inter", sans-serif;
}
Step 5: Handle Renamed Utilities
The migration tool handles most renames, but review your templates for:
shadowβshadow-smroundedβrounded-smblurβblur-sm
Use a global find-and-replace for common patterns, then verify visually.
Step 6: Update Plugins
Many v3 plugins need updates for v4. Check your plugin list:
# Check for v4-compatible versions
npm outdated
Official plugins (@tailwindcss/typography, @tailwindcss/forms) have v4-compatible releases. Third-party plugins vary β check their GitHub issues.
Container Queries
Container queries are a first-class feature in v4. Unlike media queries (which respond to the viewport), container queries respond to the parent elementβs size.
<div class="@container">
<div class="grid @sm:grid-cols-2 @lg:grid-cols-4">
<!-- columns change based on container width, not viewport -->
</div>
</div>
This is transformative for component libraries. A card component can be responsive to where itβs placed, not the page layout:
<article class="@container rounded-lg border p-4">
<img class="@sm:float-right @sm:ml-4 w-full @sm:w-48" src="...">
<h2 class="@sm:text-xl text-lg font-bold">Title</h2>
<p class="@sm:block hidden text-sm text-gray-600">Long description...</p>
</article>
Dark Mode in v4
Dark mode is simpler in v4 because of CSS variables:
@import "tailwindcss";
@theme {
--color-background: #ffffff;
--color-text: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: #0a0a0a;
--color-text: #f5f5f5;
}
}
You can also use the dark: variant for utility overrides, same as v3:
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
The difference: if you use CSS variables for semantic colors, dark mode becomes a variable swap rather than adding dark: to every element.
What Didnβt Change
Most of your HTML templates will work without modification. The utility class names are the same (except for the renamed ones covered above). The responsive variants (sm:, md:, lg:, etc.), state variants (hover:, focus:, active:), and the fundamental utility-first approach are all preserved.
If you have a large codebase, expect migration to take a few hours of careful review, not a full rewrite.
Should You Migrate Now?
Tailwind v4 is production-ready as of 2026. The migration path is well-defined and the tooling is mature.
Migrate now if:
- Build times are a pain point on your project
- You want to use container queries
- Youβre starting a new project
Wait if:
- You depend on third-party Tailwind plugins that havenβt released v4 support
- Your project has complex
tailwind.config.jscustomizations youβre not ready to audit
For new projects, v4 is the obvious choice. The CSS-first configuration model is cleaner, the performance is dramatically better, and you get access to modern CSS features without wrestling with browser compatibility.
Key Takeaways
- Tailwind v4 is 10-100x faster than v3 for build times
- Configuration moves from
tailwind.config.jsto CSS using@theme - Design tokens become real CSS custom properties, usable anywhere
- Container queries are first-class β responsive to parent, not viewport
- Run
npx @tailwindcss/upgradeto automate most of the migration - Most HTML templates work unchanged (except a few renamed utilities)
Start with a small project or a feature branch to get comfortable with the new config model. Once youβve converted one project, the rest become straightforward.
50 CLI Commands That Save Hours Every Week
The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.
- Git mastery (10 cmds)
- File & search wizardry
- Docker & DevOps tricks
- Process & network tools
- Productivity boosters
- macOS & Linux install guide
No spam. 1 email/week max. Unsubscribe anytime.
Found this guide useful? Check out our free developer tools.
Affiliate disclosure: Some links below are affiliate links β we may earn a small commission at no extra cost to you. Learn more.
Recommended Tools & Resources
DigitalOcean
$200 credit for new users. Simple, affordable cloud hosting for developers.
GitHub Student Pack
Free access to 100+ developer tools. Perfect for students and new devs.
Vercel
Deploy frontend apps instantly. Free tier is generous for side projects.
DevPlaybook Products
Boilerplates, scripts & AI toolkits to 10x your dev workflow.