TL;DR:

  • Tailwind CSS 4 replaces the JavaScript config file with a CSS-first configuration system — your tailwind.config.js becomes @theme blocks in your CSS.
  • The new Oxide engine (written in Rust and Lightning CSS) is dramatically faster: full builds that took seconds now take milliseconds, and incremental builds are near-instant.
  • Most utility class names are unchanged, but some have been renamed or restructured. The official upgrade tool handles the majority of mechanical changes automatically.

Tailwind CSS 4 shipped in stable form in early 2025 and has been the default for new projects since. If you’re migrating an existing v3 project, the changes are significant enough to require a deliberate upgrade path, but the end result is a meaningfully faster development experience and a configuration model that many teams find cleaner.

The Core Change: CSS-First Configuration

In Tailwind v3, you configured everything in tailwind.config.js. In v4, configuration moves into your CSS file using @theme:

Before (v3):

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          500: '#6366f1',
          600: '#4f46e5',
        }
      },
      fontFamily: {
        sans: ['Inter', 'sans-serif'],
      }
    }
  }
}

After (v4):

/* globals.css */
@import "tailwindcss";

@theme {
  --color-brand-500: #6366f1;
  --color-brand-600: #4f46e5;
  --font-sans: 'Inter', sans-serif;
}

The @theme block defines CSS custom properties that Tailwind v4 reads to generate utilities. Any --color-* variable becomes available as bg-{name}, text-{name}, border-{name} etc. Any --font-* variable becomes available as font-{name}. The naming conventions map predictably from CSS variable names to utility names.

This approach has some real advantages: your design tokens are native CSS custom properties, which means they’re accessible from non-Tailwind CSS, from JavaScript via getComputedStyle, and they work naturally with browser devtools.

The Oxide Engine

Tailwind v4’s engine is a complete rewrite using Rust under the hood (via the @tailwindcss/oxide package) and Lightning CSS for processing instead of PostCSS’s JavaScript-based transforms. The performance difference is substantial:

  • Cold build (no cache): ~10x faster than v3 for typical projects
  • Incremental build (file change during dev): ~100x faster — essentially instant
  • CSS output size: smaller by default because v4 drops utilities you don’t use without any purge configuration

The PostCSS plugin is still available for projects that need it, but the recommended path for new projects and Vite users is the dedicated @tailwindcss/vite plugin, which integrates directly with Vite’s module graph for optimal HMR performance.

Installation and Setup

For a new Vite project:

npm install tailwindcss @tailwindcss/vite
// vite.config.ts
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [tailwindcss()]
})
/* src/index.css */
@import "tailwindcss";

That’s it. No tailwind.config.js, no content array, no PostCSS config. The v4 engine auto-detects which files to scan using a heuristic that works correctly for most project structures.

For Next.js 15+, use @tailwindcss/postcss:

npm install tailwindcss @tailwindcss/postcss
// postcss.config.mjs
export default { plugins: { '@tailwindcss/postcss': {} } }

What Changed in the Utility Classes

Most class names are identical to v3. The breaking changes are narrower than they might seem:

Renamed utilities:

  • shadow-smshadow-xs, shadowshadow-sm (the whole shadow scale shifted down one step)
  • blur-smblur-xs, blurblur-sm (same shift)
  • rounded-smrounded-xs, roundedrounded-sm
  • ringring-3 (ring now requires an explicit size)

Removed utilities:

  • bg-opacity-*, text-opacity-*, border-opacity-* — use opacity modifier syntax instead: bg-black/50
  • overflow-ellipsistext-ellipsis
  • flex-shrink-* and flex-grow-*shrink-* and grow-* (these were already available in v3)

New utilities in v4:

  • starting: variant for CSS @starting-style (enter animations without JavaScript)
  • field-sizing-content for field-sizing: content on textareas
  • inert: variant targeting the inert HTML attribute
  • Container queries built in with @container and @md: etc. — no plugin required
  • 3D transform utilities: rotate-x-*, rotate-y-*, perspective-*

Migrating an Existing Project

The official upgrade tool handles most of the mechanical work:

npx @tailwindcss/upgrade@next

This tool:

  1. Converts tailwind.config.js to @theme blocks in your CSS
  2. Renames deprecated utility classes throughout your templates
  3. Updates package.json dependencies
  4. Migrates @apply directives where possible

The upgrade tool doesn’t handle every edge case. Manual review is needed for:

  • Custom plugins that used v3’s JavaScript plugin API (the v4 plugin API changed)
  • Complex content configuration using globs or transforms
  • safelist entries (v4 handles this differently via CSS @source)
  • JIT-mode arbitrary value syntax that relied on v3 internals

After running the tool, do a build and check the output. Most projects come through cleanly; the ones that need manual intervention typically have custom plugins or non-standard configurations.

Custom Plugins in v4

Tailwind v4’s plugin API moved to CSS. Simple utility additions now use @utility:

@utility tab-4 {
  tab-size: 4;
}

For variant plugins, use @variant:

@variant hocus (&:hover, &:focus);

JavaScript plugins that used v3’s addUtilities, addComponents, or addVariant APIs need to be ported to the CSS-based equivalents. Many popular plugins (Tailwind Typography, Tailwind Forms) have released v4-compatible versions — check their changelogs before upgrading.

Checking Compatibility

Before migrating a production project, check:

  • Framework integration: Next.js 15+, SvelteKit, Nuxt 3, Astro 4+ all have v4 support. Older versions may need their adapter packages updated.
  • UI component libraries: If you use a library built on Tailwind (Shadcn/UI, daisyUI, Headless UI), check whether they’ve shipped v4 support. Shadcn/UI updated to v4 in early 2025; daisyUI v5 shipped with v4 support.
  • CSS-in-JS: If you’re using Tailwind alongside styled-components or Emotion, the interaction model changed because v4 outputs a single CSS cascade rather than individual utility blocks.

The v4 migration is more work than a typical minor version bump, but teams that have done it report the build speed improvement alone making it worthwhile — particularly for large projects where v3 cold builds were measured in tens of seconds.

References