Tailwind CSS v4

21. June, 2025 11 min read Develop

A Ground-Up Rewrite

Tailwind CSS v4 is the most significant release in the framework's history. A complete rewrite from the ground up, it introduces CSS-first configuration, a blazing-fast new engine, and embraces modern CSS features that were simply not available when Tailwind was first created.

Released in January 2025, Tailwind CSS v4 represents a fundamental shift in how you configure and use the framework. In this post, we’ll explore everything that’s new, what’s changed, and how to migrate your existing projects.

The Oxide Engine

The headline improvement in v4 is performance. The new Oxide engine, written from scratch, delivers dramatic speed improvements across the board:

Build Type v3.4 v4.0 Improvement
Full build 378ms 100ms 3.78x faster
Incremental rebuild (new CSS) 44ms 5ms 8.8x faster
Incremental rebuild (no new CSS) 35ms 192μs 182x faster

That last number is not a typo. Incremental rebuilds with no new CSS classes now complete in microseconds. This means your development server responds almost instantly as you work, regardless of project size. For teams working on large-scale applications, this is a transformative improvement that removes the “waiting for styles to compile” bottleneck entirely.

CSS-First Configuration

The biggest paradigm shift in v4 is moving configuration from JavaScript to CSS. The familiar tailwind.config.js file is replaced by the @theme directive directly in your CSS.

The Old Way (v3)

In v3, you configured Tailwind through a JavaScript file:

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{html,js,tsx}'],
  theme: {
    extend: {
      colors: {
        brand: '#ff5733',
        accent: '#3498db',
      },
      fontFamily: {
        display: ['Satoshi', 'sans-serif'],
      },
      spacing: {
        18: '4.5rem',
      },
    },
  },
};

The New Way (v4)

In v4, everything lives in your CSS:

@import "tailwindcss";

@theme {
  --font-display: "Satoshi", "sans-serif";
  --color-brand: #ff5733;
  --color-accent: #3498db;
  --spacing-18: 4.5rem;
  --breakpoint-3xl: 1920px;
  --ease-fluid: cubic-bezier(0.3, 0, 0, 1);
}

The benefits of this approach are significant. All theme values defined in @theme are automatically exposed as native CSS custom properties on :root. This means you can access your design tokens anywhere — in inline styles, JavaScript, animation libraries, or third-party tools — without any build step. You simply use var(--color-brand) and it works.

This also means your configuration is now part of your stylesheet, living alongside the styles it affects. There’s no context-switching between JavaScript and CSS when adjusting your design system.

If you still need a JavaScript config file for plugins or complex logic, it’s still supported. However, it’s no longer auto-detected — you must explicitly reference it:

@import "tailwindcss";
@config "../../tailwind.config.js";

Simplified Setup

Getting started with Tailwind v4 is remarkably simple. The entire setup is just three steps:

1. Install Dependencies

npm install tailwindcss @tailwindcss/postcss

2. Configure PostCSS

// postcss.config.js
export default {
  plugins: ["@tailwindcss/postcss"],
};

3. Import Tailwind

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

That’s it. No more @tailwind base; @tailwind components; @tailwind utilities; directives. No more installing postcss-import or autoprefixer as separate dependencies — both are now handled automatically by the Tailwind PostCSS plugin.

Content detection is also automatic. Tailwind v4 scans your project files intelligently, respecting your .gitignore file to skip node_modules and build artifacts. The manual content array in your config is gone.

For Vite projects, there’s an even faster option with the first-party Vite plugin:

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite';

export default {
  plugins: [tailwindcss()],
};

Modern CSS Features

Tailwind v4 embraces modern CSS capabilities that weren’t widely supported when v3 was released. These features make the framework more powerful and more aligned with how CSS is evolving.

Native Cascade Layers

Tailwind now uses CSS @layer rules to organize its output. This gives you fine-grained control over specificity and ensures that Tailwind’s utility classes interact predictably with your custom styles, third-party libraries, and CSS resets.

Container Queries (Built-In)

Container queries are now a first-class feature — no plugin required. This is a big deal for component-based architecture where you want components to respond to their container’s size rather than the viewport:

<div class="@container">
  <div class="grid grid-cols-1 @sm:grid-cols-3 @lg:grid-cols-4">
    <!-- Responsive based on container width -->
  </div>
</div>

You also get @max-* variants for max-width container queries and the ability to stack ranges like @min-md:@max-xl:hidden for precise control.

Color Mix and OKLCH

The color palette has been upgraded from sRGB to the OKLCH color space, providing more vivid and perceptually balanced colors on modern wide-gamut displays. The color-mix() CSS function is used under the hood, enabling opacity modifiers on any color — including CSS custom properties and currentColor:

<div class="bg-brand/50">
  <!-- 50% opacity of your custom brand color -->
</div>

<div class="bg-(--my-custom-color)/75">
  <!-- Works with any CSS variable too -->
</div>

Registered Custom Properties

Using @property registration, Tailwind can now animate properties that were previously impossible to transition. This means you can smoothly animate gradient stops, individual transform components, and other properties that CSS transitions couldn’t handle before.

New Utilities and Variants

Tailwind v4 introduces a wealth of new utilities that expand what you can express directly in your HTML.

3D Transforms

Full 3D transform support is now built in:

<div class="perspective-500">
  <div class="rotate-x-12 rotate-y-6 transform-3d">
    <!-- 3D transformed element -->
  </div>
</div>

Available utilities include rotate-x-*, rotate-y-*, scale-z-*, translate-z-*, perspective-*, and perspective-origin-*.

Expanded Gradients

Gradients get a major upgrade with support for arbitrary angles, radial gradients, and conic gradients:

<!-- Arbitrary angle -->
<div class="bg-linear-45 from-blue-500 to-purple-500"></div>

<!-- Radial gradient (new) -->
<div class="bg-radial from-yellow-300 to-orange-500"></div>

<!-- Conic gradient (new) -->
<div class="bg-conic from-red-500 via-green-500 to-blue-500"></div>

<!-- More vivid gradients via OKLCH interpolation -->
<div class="bg-linear-to-r/oklch from-blue-500 to-green-500"></div>

Note that bg-gradient-* has been renamed to bg-linear-* to accommodate the new gradient types.

Dynamic Utility Values

One of the most practical improvements — spacing, grid columns, and other numeric utilities now accept any value without arbitrary value syntax:

<!-- v3: needed arbitrary values -->
<div class="grid-cols-[15] mt-[4.25rem]"></div>

<!-- v4: just works -->
<div class="grid-cols-15 mt-17 w-29"></div>

This removes friction for values that don’t align perfectly with the default scale.

The not-* Variant

Negate any pseudo-class or media query with the not-* variant:

<button class="opacity-100 not-hover:opacity-75">
  Subtle opacity when not hovered
</button>

<div class="not-supports-grid:flex">
  Fallback for browsers without grid
</div>

CSS-Only Enter/Exit Transitions

The starting variant enables @starting-style support for pure CSS enter and exit animations:

<dialog class="opacity-100 transition-opacity starting:open:opacity-0">
  <!-- Fades in when opened, no JavaScript needed -->
</dialog>

Other Notable Additions

  • inset-shadow-* and inset-ring-*: Stackable shadow layers (up to 4 layers)
  • field-sizing: Auto-resizing textareas without JavaScript
  • color-scheme: Control light/dark scrollbar appearance
  • font-stretch: Variable font width control
  • inert variant: Style elements with the inert attribute
  • nth-* variant: Target nth-child elements directly
  • in-* variant: Group-like targeting without adding a group class

Breaking Changes

Tailwind v4 is a major version with significant breaking changes. Here are the most important ones to be aware of.

Renamed Utility Scales

The default sizes for shadows, border-radius, and blur have been shifted down one level:

v3 v4
shadow-sm shadow-xs
shadow shadow-sm
rounded-sm rounded-xs
rounded rounded-sm
blur-sm blur-xs
blur blur-sm

This pattern applies to drop-shadow-* and backdrop-blur-* as well.

Default Behavior Changes

Several defaults have changed to be more aligned with browser standards:

  • Border color: Now currentColor instead of gray-200
  • Ring width: Now 1px instead of 3px; ring color is currentColor instead of blue-500
  • Hover variant: Only applies when the primary input supports hover (@media (hover: hover)), preventing sticky hover states on touch devices
  • outline-none: Renamed to outline-hidden; the new outline-none sets outline-style: none
  • Variant stacking order: Now left-to-right instead of right-to-left

Removed Opacity Utilities

The standalone opacity utilities like bg-opacity-*, text-opacity-*, and border-opacity-* have been removed. Use the slash modifier instead:

<!-- v3 -->
<div class="bg-black bg-opacity-50"></div>

<!-- v4 -->
<div class="bg-black/50"></div>

Custom Utilities Syntax

The @layer utilities pattern for custom utilities has been replaced with the @utility directive:

/* v3 */
@layer utilities {
  .custom-scrollbar {
    scrollbar-width: thin;
  }
}

/* v4 */
@utility custom-scrollbar {
  scrollbar-width: thin;
}

No More Preprocessor Compatibility

This is a big one: Tailwind v4 is not compatible with Sass, Less, or Stylus. Tailwind is now your CSS preprocessor. It handles imports, nesting, and vendor prefixing natively. If your project relies on Sass features, you’ll need to migrate those styles to plain CSS or Tailwind utilities before upgrading.

CSS Variable Syntax Change

Arbitrary values using CSS variables now use parentheses instead of square brackets:

<!-- v3 -->
<div class="bg-[--brand-color]"></div>

<!-- v4 -->
<div class="bg-(--brand-color)"></div>

Migration Guide

Upgrading from v3 to v4 is made easier by an official migration tool. Here’s the recommended approach:

1. Create a New Branch

Always migrate on a separate branch so you can compare the changes:

git checkout -b tailwind-v4-migration

2. Run the Upgrade Tool

The official CLI tool handles most of the migration automatically:

npx @tailwindcss/upgrade

This tool will:

  • Migrate your tailwind.config.js to CSS @theme configuration
  • Rename deprecated utilities in your templates
  • Update build tool configurations
  • Adjust PostCSS and Vite configurations

It requires Node.js 20 or later.

3. Review and Test

After the automated migration, review the diff carefully. Pay special attention to:

  • Responsive layouts: The hover variant behavior change may affect touch device experiences
  • Dark mode: Ensure your dark mode implementation still works correctly
  • Custom components: Any custom CSS using @layer utilities needs to use @utility instead
  • Third-party libraries: Some UI libraries may not yet support v4’s cascade layer ordering

4. Manual Adjustments

Some things the migration tool can’t automate:

  • Removing Sass/Less dependencies and rewriting those styles
  • Adjusting custom plugins that rely on the JavaScript API
  • Updating tests that assert on specific class names or CSS output

Should You Upgrade?

If you’re starting a new project, there’s no question — use v4. The performance improvements alone are worth it, and the CSS-first configuration is more intuitive once you get used to it. The simplified setup means you’ll be productive in minutes rather than spending time configuring build tools.

For existing projects, the answer depends on your project’s complexity and dependencies. Small to medium projects should upgrade without much friction — the migration tool handles the heavy lifting and most changes are straightforward renames. Large projects with extensive Sass usage, custom plugins, or tight coupling to v3 internals may need a more gradual approach. In those cases, consider migrating one module or section at a time rather than attempting a full migration in one go.

The browser support floor is also worth considering. Tailwind v4 requires Safari 16.4+, Chrome 111+, and Firefox 128+. If you need to support older browsers, you’ll need to stay on v3 for now. For most modern web applications though, this browser matrix covers the vast majority of users.

One common concern is third-party component library compatibility. Libraries like shadcn/ui, Headless UI, and Radix already support v4, but if you rely on smaller or less-maintained Tailwind plugins, verify compatibility before upgrading. The removal of the JavaScript plugin API means some plugins need to be rewritten for v4.

Finally, if you’re using a meta-framework like Next.js, Remix, or Nuxt, check their documentation for v4-specific guidance. Most have first-class support, but there may be subtle configuration differences depending on your bundler setup.

Conclusion

Tailwind CSS v4 is a bold release that moves the framework forward in every dimension. The CSS-first configuration eliminates the JavaScript-CSS context switching that was always slightly awkward. The Oxide engine makes builds so fast they’re essentially invisible. And the embrace of modern CSS features like container queries, cascade layers, and OKLCH colors positions Tailwind well for the next era of web development.

The breaking changes are real, but the migration tool smooths the path significantly. Whether you’re upgrading an existing project or starting fresh, Tailwind v4 delivers a better developer experience with less configuration and faster builds.

‘Till next time!