Tailwind CSS 4 Guide 2026 — New Engine, CSS Variables, and Utility Patterns

Sanjeev SharmaSanjeev Sharma
4 min read

Advertisement

Introduction

Why This Matters

Tailwind CSS 4 rewrites the engine in Rust (Oxide), moves configuration to CSS, and ships first-class container queries. It is 5–10x faster to build and produces smaller output — all with zero PostCSS config required for most projects.

Installation and Setup

Tailwind 4 uses a Vite plugin or standalone CLI instead of PostCSS:

npm install tailwindcss @tailwindcss/vite
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
 
export default defineConfig({
  plugins: [tailwindcss()],
})
/* src/app.css — replaces tailwind.config.js */
@import "tailwindcss";
 
@theme {
  --font-sans: 'Inter', sans-serif;
  --color-brand: oklch(60% 0.2 250);
  --color-brand-dark: oklch(45% 0.2 250);
  --spacing-18: 4.5rem;
  --radius-card: 0.75rem;
}

CSS Variable Tokens

In Tailwind 4, the design system lives in CSS — not JavaScript:

@theme {
  --color-primary: oklch(55% 0.22 264);
  --color-primary-hover: oklch(48% 0.22 264);
  --color-success: oklch(65% 0.18 145);
  --color-danger: oklch(60% 0.24 25);
 
  --font-heading: 'Cal Sans', sans-serif;
  --text-display: 3.5rem;
  --leading-display: 1.1;
 
  --spacing-section: 5rem;
  --spacing-prose: 65ch;
}

Use tokens directly as utilities:

<div class="bg-primary text-white p-4 rounded-card hover:bg-primary-hover">
  Token-driven component
</div>

Container Queries

Tailwind 4 ships container queries without a plugin:

<div class="@container">
  <div class="grid grid-cols-1 @md:grid-cols-2 @xl:grid-cols-3 gap-4">
    <Card />
    <Card />
    <Card />
  </div>
</div>

Named containers for nested layouts:

<div class="@container/sidebar">
  <nav class="flex-col @sm/sidebar:flex-row">
    <!-- Changes based on sidebar width, not viewport -->
  </nav>
</div>

Variant and Utility Patterns

New variants in Tailwind 4:

<!-- starting: variant for CSS mount animations -->
<div class="opacity-0 starting:opacity-0 transition-opacity duration-500">
  Fades in on mount
</div>
 
<!-- :not() variant -->
<li class="not-first:border-t">Border on all except first</li>
 
<!-- Named group variants -->
<div class="group/card hover:shadow-lg">
  <button class="opacity-0 group-hover/card:opacity-100">
    Show on card hover
  </button>
</div>
 
<!-- Arbitrary grid -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-6">
  Auto-fill responsive grid
</div>

Component Pattern with cva

import { cva, type VariantProps } from 'class-variance-authority'
 
const button = cva(
  'inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2',
  {
    variants: {
      variant: {
        primary: 'bg-primary text-white hover:bg-primary-hover',
        secondary: 'bg-white text-primary border border-primary hover:bg-primary/5',
        ghost: 'text-primary hover:bg-primary/10',
      },
      size: {
        sm: 'px-3 py-1.5 text-sm',
        md: 'px-4 py-2 text-base',
        lg: 'px-6 py-3 text-lg',
      },
    },
    defaultVariants: { variant: 'primary', size: 'md' },
  }
)
 
export function Button({
  variant,
  size,
  className,
  ...props
}: React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof button>) {
  return <button className={button({ variant, size, className })} {...props} />
}

Migrating from Tailwind v3

npx @tailwindcss/upgrade
v3v4
tailwind.config.js@theme {} in CSS
bg-opacity-50bg-black/50
ring-opacity-*ring-color/opacity
PostCSS requiredVite plugin or CLI

Common Mistakes

  • Using tailwind.config.js instead of migrating tokens to @theme {} in CSS
  • Overusing @apply inside components when class composition is more maintainable
  • Forgetting to mark a parent with @container before using @sm: breakpoints on children
  • Using the same arbitrary value repeatedly instead of adding it to @theme
  • Not running the upgrade codemod before manually editing deprecated utilities

Best Practices

  • Define all design tokens in @theme {} so they become CSS custom properties automatically
  • Use container queries for component-level responsiveness and viewport queries for layout
  • Use cva (class-variance-authority) for multi-variant component APIs
  • Keep arbitrary values rare — three repetitions means it belongs in @theme
  • Use oklch colors for perceptually uniform, accessible color scales

Key Takeaways

  • Tailwind 4 uses an Oxide (Rust) engine that is 5–10x faster than v3 at build time
  • Configuration moves from tailwind.config.js to @theme {} inside a CSS file
  • Tokens defined in @theme automatically become CSS custom properties available site-wide
  • Container queries ship without any plugin in v4 using the @container class
  • The starting: variant enables CSS-native mount animations without JavaScript
  • @tailwindcss/upgrade codemod automates most of the v3-to-v4 migration
  • oklch is the recommended color space for defining brand palettes in @theme
  • Named group/{name} and peer/{name} variants allow targeting specific ancestors

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading