Tailwind CSS has been the dominant way developers write styles on the web for over five years. But as build systems transitioned from Webpack to high-speed tools like Vite, Esbuild, and Turbopack, Tailwind’s Javascript-heavy configuration and PostCSS parsing engine began to feel like a performance bottleneck.

With the release of Tailwind CSS v4, the framework has been completely rewritten.

By replacing the Javascript-based engine with a high-performance compiler written in Rust, Tailwind v4 compiles styles up to 10 times faster. More importantly, it discards tailwind.config.js entirely, moving to a modern, CSS-First Configuration model.

Here is a practical guide to upgrading your codebase and leveraging Tailwind v4’s new features.


1. Rust-Powered Compiler & Vite Integration

In Tailwind v3, the compiler scanned your files for class names using Javascript regex patterns, then resolved styles against a massive Javascript configuration object. Under the hood, this was parsed by PostCSS.

Tailwind v4 shifts execution to Rust. It directly hooks into your bundler (like Vite) to scan files in parallel:

  • 10x Faster HMR (Hot Module Replacement): CSS updates apply in under 5 milliseconds.
  • Vite-Native Plugin: Autoprefixer and PostCSS configuration files are no longer required. You simply declare the Tailwind plugin in your Vite config.

For example, in a modern Astro project:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwind from '@tailwindcss/vite';

export default defineConfig({
  vite: {
    plugins: [tailwind()],
  },
});

2. CSS-First Configuration: Goodbye tailwind.config.js

The most visible change in Tailwind v4 is the removal of tailwind.config.js.

In v3, defining a custom color palette or font family required writing massive Javascript objects. In v4, your CSS file is the configuration file.

You now import Tailwind and configure your theme using the standard CSS @theme directive:

/* src/styles/global.css */
@import "tailwindcss";

@theme {
  --font-sans: "Outfit Variable", sans-serif;
  --font-serif: "Source Serif 4 Variable", serif;

  --color-primary: #d4380d;
  --color-accent: #fa541c;
  --color-background-warm: #fafaf8;
  
  --spacing-128: 32rem;
}

How this compiles:

When the Rust compiler reads your CSS file:

  1. It parses the custom CSS custom properties (variables) defined inside @theme.
  2. It automatically generates the corresponding utility classes—for example, --color-primary immediately yields bg-primary, text-primary, and border-primary.
  3. It exposes these custom properties globally, meaning they are also standard CSS variables you can use in raw CSS files: background-color: var(--color-primary).

3. Scoping Content Paths Automatically

In Tailwind v3, you had to explicitly configure the content array to tell the compiler where your HTML, JSX, and TSX files lived:

// Legacy tailwind.config.js
module.exports = {
  content: ["./src/**/*.{html,js,jsx,ts,tsx,astro}"],
}

If you forgot to add a folder path, your utility classes wouldn’t compile, resulting in unstyled pages.

Tailwind v4 removes the content array entirely. The Rust compiler automatically scans your bundler’s dependency graph. Any file processed by Vite, Rollup, or Webpack that imports your CSS bundle is scanned for utility classes automatically. It just works.


4. Declaring Custom Utilities Natively

In Tailwind v3, adding custom utility classes required writing Javascript plugins or using complex CSS structures. In v4, you can write custom utilities natively in your CSS file using the @utility directive:

/* Custom utility declaration */
@utility scrollbar-hide {
  &::-webkit-scrollbar {
    display: none;
  }
  -ms-overflow-style: none;
  scrollbar-width: none;
}

This registers scrollbar-hide as a first-class Tailwind class, complete with support for variants like hover:scrollbar-hide and responsive breakpoints like md:scrollbar-hide.


5. Upgrade Checklist for Tailwind v4

If you are migrating a production application from v3 to v4, follow this checklist:

  1. Uninstall Legacy Deps: Remove postcss, autoprefixer, and your old tailwind.config.js.
  2. Install modern packages: Install tailwindcss and @tailwindcss/vite (or equivalent bundler plugin).
  3. Rewrite Imports: Replace @tailwind base; @tailwind components; @tailwind utilities; in your main CSS file with a single @import "tailwindcss";.
  4. Migrate Theme Config: Convert your theme block from tailwind.config.js into CSS Custom Properties inside the @theme block.
  5. Update custom classes: Convert any custom components or classes using @apply or custom utility wrappers to CSS custom properties.

A Streamlined Developer Experience

Tailwind CSS v4 is a significant evolutionary step. By alignment with native CSS custom properties and shifting compiling to Rust, it eliminates build latency while simplifying configuration files.

Writing styles feels less like configuring a library, and more like writing modern, standard CSS.