migration2023-12-20·12 min·332/348

Migrating to Tailwind CSS 4.0 in Next.js Projects

Step-by-step guide to migrating from Tailwind CSS 3.x to 4.0 in Next.js with App Router

Migrating to Tailwind CSS 4.0 in Next.js Projects

Introduction

Tailwind CSS 4.0 is a major release that changes how the framework is configured and compiled. The new Oxide engine provides significantly faster build times, but the migration from 3.x requires attention to configuration changes, new features, and deprecated utilities.

After migrating a production Next.js 14 application from Tailwind 3.4 to 4.0, I documented every breaking change and optimization opportunity. The build time improvement was dramatic: from 4.2 seconds to 0.8 seconds for a 500-component project.

Environment

  • OS: Windows 11
  • Node.js: v20.10.0
  • Next.js: 14.0.4
  • Tailwind CSS: 3.4.1 to 4.0.0
  • PostCSS: 8.4.32

Problem

After updating to Tailwind CSS 4.0, several issues occurred:

Error: PostCSS plugin "tailwindcss" requires Tailwind CSS 3.x
Warning: Unknown utility class "text-balance"
Error: Cannot resolve module "tailwindcss/theme"

The configuration file format changed completely between versions.

Solution

Step 1: Update dependencies

# Remove old dependencies
npm uninstall tailwindcss postcss autoprefixer @tailwindcss/typography

# Install Tailwind CSS 4.0
npm install tailwindcss@latest @tailwindcss/postcss@latest

# For Next.js integration
npm install @tailwindcss/postcss

Step 2: Update PostCSS configuration

// postcss.config.js (Tailwind 4.0)
module.exports = {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

Step 3: Migrate CSS configuration

/* app/globals.css (Tailwind 4.0) */
@import "tailwindcss";

/* Custom theme configuration */
@theme {
  --color-primary: #3b82f6;
  --color-secondary: #64748b;
  --color-accent: #f59e0b;

  --font-sans: 'Inter', system-ui, sans-serif;
  --font-mono: 'Fira Code', monospace;

  --spacing-xs: 0.25rem;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
  --spacing-xl: 2rem;
}

/* Custom utilities */
@utility container {
  margin-inline: auto;
  padding-inline: 1rem;
  max-width: 1200px;
}

/* Dark mode */
@variant dark (&:where(.dark, .dark *));

Step 4: Update component classes

// Before (Tailwind 3.x)
// After (Tailwind 4.0) - Most classes remain the same
// New text balance utility

Title

// New color-mix based opacity

Step 5: Migrate custom plugins

// tailwind.config.js (OLD - Tailwind 3.x)
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.text-shadow': {
          textShadow: '0 2px 4px rgba(0,0,0,0.1)',
        },
      })
    }),
  ],
}
/* app/globals.css (NEW - Tailwind 4.0) */
@utility text-shadow {
  text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

@utility text-shadow-lg {
  text-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

Step 6: Handle deprecated utilities

// Deprecated in 4.0 - Use new alternatives
// OLD: bg-opacity-50
// NEW: bg-primary/50

// OLD: text-opacity-75
// NEW: text-primary/75

// OLD: border-opacity-25
// NEW: border-primary/25

// OLD: ring-opacity-50
// NEW: ring-primary/50

Lessons Learned

  1. Delete tailwind.config.js after migration. Tailwind 4.0 uses CSS-based configuration exclusively. Keeping the old config file causes conflicts.

  2. Use the official migration tool. Run npx @tailwindcss/upgrade to automatically convert most configuration and class names.

  3. Test every page after migration. Subtle class name changes can cause layout shifts that are not immediately obvious.

  4. Benefit from automatic content detection. Tailwind 4.0 automatically detects source files, eliminating the content array in configuration.

  5. Leverage the new Oxide engine. The build time improvement is significant. If you are still on 3.x, upgrading is worth the migration effort.

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.