Tailwind CSS v4 Migration: What Changed from v3
Key changes in Tailwind CSS v4 and how to migrate from v3. CSS-based config, new utilities, and the Oxide engine.

Tailwind CSS v4 looks similar to v3 on the surface, but the internals changed substantially. The most visible shift: tailwind.config.js is gone. Configuration now lives directly in your CSS file. It feels odd at first, but once you get used to it, it's actually more intuitive.
The Biggest Change — Config Moved to CSS
In v3, you defined colors, fonts, breakpoints, and other design tokens as a JavaScript object in tailwind.config.js. In v4, you define them inside your CSS file using the @theme directive.
/* v3: tailwind.config.js */
/* module.exports = {
theme: {
extend: {
colors: {
brand: '#3b82f6',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
} */
/* v4: app.css */
@import "tailwindcss";
@theme {
--color-brand: #3b82f6;
--font-sans: 'Inter', sans-serif;
}
You're defining CSS custom properties directly. No JavaScript config file means a simpler build chain, and you can see all your design tokens by just looking at the CSS.
No More content Configuration
The content array was one of the most common sources of frustration in v3. You had to specify which files use Tailwind classes, and forgetting a path meant styles silently didn't apply.
// v3: everyone has gotten bitten by this at least once
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
}
v4 uses automatic content detection by default. It scans your project directory and finds classes on its own. No content config needed. For some people, this alone is reason enough to migrate.
If you need to exclude or include specific paths, use the @source directive:
@import "tailwindcss";
@source "../node_modules/some-ui-lib";
New Engine — Oxide
v4 runs on a new Rust-based engine called Oxide. What you'll notice:
Build speed — Significantly faster than v3, especially on large projects. Instead of running as a PostCSS plugin, it operates as a standalone CSS processing engine.
Simpler installation — No need to install postcss and autoprefixer separately. One plugin handles everything: @tailwindcss/postcss or @tailwindcss/vite.
# v3
npm install tailwindcss postcss autoprefixer
# v4
npm install tailwindcss @tailwindcss/vite # Vite projects
Changed Utilities
Color Opacity
<!-- v3 -->
<div class="bg-blue-500/50">
<!-- v4 — same syntax still works, plus CSS variable control -->
<div class="bg-blue-500/50">
<div class="bg-[oklch(0.5_0.2_250/50%)]">
v4 uses the oklch color space internally. You can use oklch values directly, which is useful because oklch is perceptually uniform — maintaining consistent lightness across a color palette becomes much easier.
New Utilities
<!-- Container queries -->
<div class="@container">
<div class="@lg:flex @md:grid">...</div>
</div>
<!-- 3D transforms -->
<div class="rotate-x-45 perspective-800">
<!-- Gradient improvements -->
<div class="bg-linear-to-r from-blue-500 to-purple-500">
<!-- bg-gradient-to-r → bg-linear-to-r -->
Container queries are now built in. In v3, you needed the @tailwindcss/container-queries plugin. v4 includes them natively. Components can adapt their layout based on their parent's size rather than the viewport — a big deal for reusable components.
Renamed Utilities
Some utilities got more consistent names:
| v3 | v4 |
|---|---|
bg-gradient-to-r | bg-linear-to-r |
bg-opacity-50 | bg-black/50 (already worked in v3) |
shadow-sm | shadow-xs (new size step added) |
Most v3 syntax still works, and the automated migration tool handles the renamed ones.
Migration in Practice
1. The Automatic Migration Tool
An official tool is available:
npx @tailwindcss/upgrade
What it does:
- Converts
tailwind.config.jssettings to CSS@themeblocks - Renames changed utility classes automatically
- Updates import structure
- Cleans up PostCSS config
It's not perfect, but it handles the bulk of the conversion. Fix the rest manually.
2. Watch Out For
Plugin compatibility — v3 plugins won't necessarily work in v4. Official plugins like @tailwindcss/typography and @tailwindcss/forms have been updated, but community plugins may need checking.
PostCSS config changes — v4 uses a dedicated plugin (@tailwindcss/postcss or @tailwindcss/vite) instead of the PostCSS plugin approach. Your postcss.config.js needs updating.
Complex JS-based customizations — If you used functions in tailwind.config.js to dynamically generate values, those won't translate 1:1 to CSS @theme. You'll need to combine CSS custom properties with the @utility directive to achieve the same result.
3. Recommended Order
- Start from a clean git commit
- Run
npx @tailwindcss/upgrade - Build and check for errors
- Visually inspect pages, fixing broken styles manually
- Verify plugin compatibility
For large projects, check page by page rather than trying to verify everything at once.
Should You Migrate?
New projects — start with v4. Simpler config, faster builds, more features.
Existing projects — no rush. v3 will be maintained for a while. But if you want container queries, 3D transforms, or faster builds, there's plenty of reason to migrate. The automated tool makes it a smaller effort than it might seem.