Tailwind CSS 4.0: What Changed and How to Migrate

Tailwind CSS 4 Migration Guide: Oxide Engine, CSS-First Configuration, and New Features

Tailwind CSS 4 is a ground-up rewrite with a new Rust-based engine called Oxide that delivers 10x faster builds and introduces CSS-first configuration — replacing the JavaScript tailwind.config.js with CSS @theme directives. Tailwind CSS 4 migration requires understanding these fundamental changes before upgrading your project. Therefore, this guide covers the new features, the migration process, and the gotchas that will save you hours of debugging.

The Oxide Engine: Why It’s 10x Faster

Tailwind 3’s JavaScript-based engine scanned your source files, generated CSS, and ran through PostCSS — all in Node.js. The Oxide engine rewrites the critical path in Rust, with parallel file scanning, zero-copy parsing, and incremental compilation. Moreover, the Oxide engine detects changes at the character level, so editing a single class only regenerates that specific utility instead of the entire stylesheet.

For large projects, build times drop from 300-500ms to 30-50ms. Hot module replacement feels instant because Tailwind processes only the changed file. Additionally, the Oxide engine reduces memory usage by 50% because it doesn’t load the entire project AST into memory. In contrast, Tailwind 3 held a JavaScript object representing every possible utility class.

/* tailwind.css — CSS-first configuration replaces tailwind.config.js */
@import "tailwindcss";

/* Define your theme with @theme — replaces module.exports config */
@theme {
  --color-primary: #3b82f6;
  --color-primary-dark: #1d4ed8;
  --color-secondary: #8b5cf6;
  --color-surface: #0f172a;
  --color-surface-light: #1e293b;

  --font-sans: 'Inter', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', monospace;

  --breakpoint-xs: 475px;  /* Custom breakpoint */

  --animate-fade-in: fade-in 0.3s ease-out;
  --animate-slide-up: slide-up 0.4s ease-out;
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slide-up {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}
Tailwind CSS 4 Oxide engine performance comparison
The Oxide engine’s Rust-based architecture delivers 10x faster builds with 50% less memory

CSS-First Configuration: Goodbye tailwind.config.js

The biggest conceptual change is moving configuration from JavaScript to CSS. Your tailwind.config.js is replaced by @theme blocks in your CSS file. Custom colors become CSS custom properties with a --color- prefix, fonts use --font-, spacing uses --spacing-, and so on. Consequently, your configuration lives alongside your other CSS, and you can use CSS features like @media and calc() directly in your theme.

Plugins also change. JavaScript plugins that added utilities via addUtilities() are replaced by CSS @utility directives. This is simpler for most use cases but means complex programmatic plugins need rethinking. Furthermore, the @apply directive still works but is discouraged — Tailwind 4 improves the developer experience enough that inline utilities are practical for more situations.

/* Custom utilities in CSS — replaces JavaScript plugins */
@utility text-balance {
  text-wrap: balance;
}

@utility glass {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.15);
}

/* Custom variants */
@variant hocus (&:hover, &:focus-visible);
@variant group-hocus (group:hover &, group:focus-visible &);

/* Usage: <div class="glass hocus:bg-white/20 p-6"> */

Migration from Tailwind v3: Step by Step

Start by running the official upgrade tool: npx @tailwindcss/upgrade. It converts your config to CSS-first format, updates deprecated class names, and adjusts your PostCSS configuration. However, the automated tool doesn’t catch everything — review the output carefully.

Key breaking changes to watch for: the @tailwind base/components/utilities directives are replaced by a single @import "tailwindcss". Color opacity modifiers like bg-blue-500/50 still work, but the theme() function in CSS changes to standard CSS custom properties. Additionally, some default spacing and color values have changed, so visually audit your pages after migration.

# Step 1: Run the automated upgrade tool
npx @tailwindcss/upgrade

# Step 2: Install new dependencies
npm install tailwindcss@latest @tailwindcss/vite

# Step 3: Update vite.config.js
# Remove postcss-related tailwind plugins
# Add @tailwindcss/vite plugin

# Step 4: Update your CSS entry point
# Before (v3):
#   @tailwind base;
#   @tailwind components;
#   @tailwind utilities;
#
# After (v4):
#   @import "tailwindcss";
#   @theme { ... }

# Step 5: Delete tailwind.config.js (after migrating to @theme)
# Step 6: Visual regression testing
// vite.config.js — Tailwind 4 with Vite
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),  // Replaces PostCSS plugin
  ],
});
Tailwind CSS 4 migration code changes and configuration
The migration tool automates most changes — but visual regression testing catches edge cases

New Features Worth Adopting

Container queries are now built-in with the @container variant. Instead of responsive breakpoints based on viewport width, components respond to their container’s width. This makes truly reusable components that work in sidebars, modals, and full-width layouts without media query hacks. For example, a product card can switch from horizontal to vertical layout based on whether it’s in a three-column grid or a narrow sidebar.

The field-sizing: content utility auto-sizes textareas and inputs to fit their content. 3D transforms are first-class with rotate-x-*, rotate-y-*, and perspective-* utilities. Furthermore, color mixing with color-mix() lets you create dynamic tints and shades without defining every shade in your theme.

Common Migration Pitfalls

Watch out for these issues: custom colors defined with theme.extend.colors in the old config need manual migration to @theme CSS variables. The @apply directive doesn’t support opacity modifiers like bg-blue-500/20 in v4 (use raw CSS rgba() instead). Additionally, any JavaScript that reads tailwind.config.js programmatically needs updating since the file no longer exists.

Plugin compatibility varies. Official plugins (@tailwindcss/typography, @tailwindcss/forms) have v4 versions. Third-party plugins may not be updated yet. As a result, check plugin compatibility before upgrading and prepare fallback CSS for unsupported plugins.

Tailwind CSS 4 new features and container queries
Container queries enable truly responsive components that adapt to their parent, not the viewport

Related Reading:

Resources:

In conclusion, Tailwind CSS 4 delivers significant performance improvements through the Oxide engine and simplifies configuration with CSS-first @theme directives. The migration is straightforward for most projects — run the upgrade tool, update your build config, and visually test your pages. New features like container queries and built-in 3D transforms expand what’s possible with utility-first CSS. Start migration on a feature branch and test thoroughly before merging.

Scroll to Top