Tailwind CSS 4 Guide 2026 — New Engine, CSS Variables, and Utility Patterns
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| v3 | v4 |
|---|---|
tailwind.config.js | @theme {} in CSS |
bg-opacity-50 | bg-black/50 |
ring-opacity-* | ring-color/opacity |
| PostCSS required | Vite plugin or CLI |
Common Mistakes
- Using
tailwind.config.jsinstead of migrating tokens to@theme {}in CSS - Overusing
@applyinside components when class composition is more maintainable - Forgetting to mark a parent with
@containerbefore 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
oklchcolors 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.jsto@theme {}inside a CSS file - Tokens defined in
@themeautomatically become CSS custom properties available site-wide - Container queries ship without any plugin in v4 using the
@containerclass - The
starting:variant enables CSS-native mount animations without JavaScript @tailwindcss/upgradecodemod automates most of the v3-to-v4 migrationoklchis the recommended color space for defining brand palettes in@theme- Named
group/{name}andpeer/{name}variants allow targeting specific ancestors
Advertisement