
Tailwind CSS v4 in 2026: The Complete Guide with Practical Examples
π· Bibek ghosh / PexelsTailwind CSS v4 in 2026: The Complete Guide with Practical Examples
Master Tailwind CSS v4 with this complete guide. Learn the new CSS-first configuration, Oxide engine, new utilities, dark mode, and migration from v3.
Tailwind CSS v4 represents the biggest overhaul the framework has seen since its inception. Released in early 2025 and now fully mature in 2026, v4 introduces a CSS-first configuration system, a completely rewritten engine called Oxide, dramatic performance improvements, and a modernized set of utilities. If you have been using Tailwind v3, upgrading to v4 changes how you think about configuration and theming. This guide walks through everything you need to know.
What Changed in Tailwind CSS v4
Tailwind v4 is not just an incremental update. It is a fundamental rethinking of how the framework works under the hood. Here are the headline changes:
- CSS-first configuration: No more
tailwind.config.js. Theme values, custom utilities, and variants are all defined directly in CSS using@themeand other directives. - Oxide engine: A new high-performance engine written in Rust that handles parsing, compilation, and class detection orders of magnitude faster than v3.
- Modern CSS features: Built-in support for
@layer, cascade layers,color-mix(),oklch(), container queries, and@starting-stylefor animations. - Simplified installation: Just one package with zero configuration required to get started.
- New default theme: An expanded color palette using OKLCH, updated spacing scale, and improved typography defaults.
Getting Started with Tailwind CSS v4
Installation
Setting up Tailwind v4 is simpler than ever. There is no separate PostCSS plugin or config file needed.
# Install Tailwind CSS v4
npm install tailwindcss @tailwindcss/vite
# Or with the CLI
npm install tailwindcss @tailwindcss/cli
For a Vite-based project, add the plugin to your Vite config:
// vite.config.ts
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
tailwindcss(),
],
});
Then import Tailwind in your main CSS file:
/* app.css */
@import "tailwindcss";
That is the entire setup. No tailwind.config.js, no postcss.config.js, no content paths to configure. The Oxide engine automatically detects your source files and scans them for class names.
Using the CLI
If you are not using Vite, the CLI works just as well:
npx @tailwindcss/cli -i app.css -o output.css --watch
CSS-First Configuration with @theme
The biggest conceptual shift in v4 is that all customization happens in CSS, not JavaScript. The @theme directive replaces the old tailwind.config.js theme object.
Defining Custom Colors
@import "tailwindcss";
@theme {
--color-brand: #4f46e5;
--color-brand-light: #818cf8;
--color-brand-dark: #3730a3;
--color-surface: #f8fafc;
--color-surface-dark: #1e293b;
}
These CSS variables automatically become available as Tailwind utilities:
<div class="bg-brand text-white">
<h1 class="text-brand-light">Hello, Tailwind v4</h1>
</div>
Custom Spacing and Sizing
@theme {
--spacing-18: 4.5rem;
--spacing-128: 32rem;
--width-content: 72rem;
--width-sidebar: 20rem;
}
Custom Fonts
@theme {
--font-sans: "Inter", "system-ui", sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;
--font-display: "Cal Sans", "Inter", sans-serif;
}
Overriding vs Extending the Default Theme
By default, @theme extends the built-in theme. If you want to completely replace a namespace, use the --* wildcard reset:
@theme {
/* Remove all default colors, only use these */
--color-*: initial;
--color-white: #ffffff;
--color-black: #000000;
--color-primary: #2563eb;
--color-secondary: #7c3aed;
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-900: #111827;
}
The Oxide Engine
Under the hood, Tailwind v4 uses a new engine called Oxide, written in Rust and compiled to native code. The performance difference is substantial.
Performance Improvements
The Oxide engine delivers dramatic speed improvements compared to the v3 JavaScript-based engine:
- Initial build times are typically 3-10x faster, depending on project size.
- Incremental rebuilds during development are nearly instantaneous, often under 5 milliseconds.
- Memory usage is significantly lower since Rust manages memory without a garbage collector.
For large monorepo projects with hundreds of thousands of classes, the difference is especially noticeable. Where v3 might take several seconds for a full rebuild, v4 completes in hundreds of milliseconds.
Automatic Content Detection
One of the best quality-of-life improvements is that you no longer need to specify content paths. The Oxide engine automatically detects and scans your project files. It uses heuristics to find template files, JSX/TSX components, and other sources of class names.
If you need to explicitly include or exclude files, you can use the @source directive:
@import "tailwindcss";
/* Add additional source paths */
@source "../shared-components/**/*.tsx";
/* Exclude a path */
@source not "../node_modules";
New and Updated Utility Classes
Tailwind v4 introduces several new utilities and refines existing ones to take advantage of modern CSS features.
Container Queries
Container queries let you style elements based on the size of their parent container rather than the viewport. Tailwind v4 has first-class support.
<div class="@container">
<div class="flex flex-col @md:flex-row @lg:grid @lg:grid-cols-3 gap-4">
<div class="p-4 bg-white rounded-lg">Card 1</div>
<div class="p-4 bg-white rounded-lg">Card 2</div>
<div class="p-4 bg-white rounded-lg">Card 3</div>
</div>
</div>
The @container class establishes a containment context, and the @md:, @lg: prefixes apply styles based on the container width.
Modern Color Functions
Tailwind v4 uses OKLCH colors by default, which provides a perceptually uniform color space. You can also use color-mix() for dynamic color manipulation:
@theme {
--color-primary: oklch(0.6 0.25 265);
--color-primary-hover: oklch(0.5 0.25 265);
}
<button class="bg-primary hover:bg-primary-hover text-white px-4 py-2 rounded">
Click me
</button>
3D Transforms
<div class="perspective-500">
<div class="rotate-y-12 hover:rotate-y-0 transition-transform duration-300">
<img src="/card.jpg" alt="3D card" class="rounded-xl shadow-lg" />
</div>
</div>
New Gradient Utilities
V4 extends gradient support with additional features:
<!-- Gradient with interpolation in OKLCH for smoother transitions -->
<div class="bg-linear-to-r from-blue-500 to-purple-500 bg-interpolate-oklch">
Smooth gradient
</div>
<!-- Conic gradient -->
<div class="bg-conic from-red-500 via-yellow-500 to-green-500">
Color wheel
</div>
The not- Variant
The not- variant inverts any other variant, powered by CSS :not():
<div class="opacity-50 not-hover:opacity-100">
Fades on hover instead of appearing
</div>
<input class="border-gray-300 not-focus:border-transparent" />
Starting Style for Animations
The starting variant lets you define styles for the @starting-style rule, which enables entry animations on elements that appear in the DOM:
<dialog class="opacity-0 starting:opacity-0 open:opacity-100 transition-opacity">
<p>This dialog fades in when opened</p>
</dialog>
Responsive Design in v4
Responsive design works the same way conceptually, with the familiar breakpoint prefix syntax. However, v4 uses modern CSS features internally.
Default Breakpoints
The default breakpoints remain practical:
| Prefix | Min Width | Common Use |
|---|---|---|
sm | 640px | Large phones, landscape |
md | 768px | Tablets |
lg | 1024px | Small laptops |
xl | 1280px | Desktops |
2xl | 1536px | Large screens |
Custom Breakpoints
@theme {
--breakpoint-xs: 475px;
--breakpoint-3xl: 1920px;
}
<div class="grid grid-cols-1 xs:grid-cols-2 md:grid-cols-3 3xl:grid-cols-4">
<!-- Responsive grid -->
</div>
Responsive Layout Example
<header class="flex flex-col sm:flex-row items-center justify-between p-4 lg:px-8">
<a href="/" class="text-xl font-bold">Brand</a>
<nav class="hidden md:flex gap-6 text-sm font-medium">
<a href="/features" class="hover:text-brand">Features</a>
<a href="/pricing" class="hover:text-brand">Pricing</a>
<a href="/docs" class="hover:text-brand">Docs</a>
</nav>
<button class="md:hidden p-2" aria-label="Menu">
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</header>
Dark Mode
Tailwind v4 continues to support dark mode with the dark: variant. By default, it uses the prefers-color-scheme media query, but you can switch to class-based or selector-based toggling.
Basic Dark Mode
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 min-h-screen">
<h1 class="text-2xl font-bold">Welcome</h1>
<p class="text-gray-600 dark:text-gray-400">This adapts to your system theme.</p>
</div>
Class-Based Dark Mode
To toggle dark mode with JavaScript rather than relying on the system setting:
@import "tailwindcss";
@variant dark (&:where(.dark, .dark *));
Now dark mode activates when a parent element has the dark class:
<html class="dark">
<body class="bg-white dark:bg-gray-950">
<!-- Dark mode active -->
</body>
</html>
// Toggle dark mode with JavaScript
function toggleDarkMode() {
document.documentElement.classList.toggle('dark');
}
Building a Theme-Aware Component
<div class="rounded-xl border border-gray-200 dark:border-gray-800
bg-white dark:bg-gray-900
shadow-sm dark:shadow-gray-950/50
p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
Settings
</h3>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
Manage your account preferences.
</p>
<button class="mt-4 px-4 py-2 rounded-lg
bg-brand text-white
hover:bg-brand-dark
focus:outline-none focus:ring-2 focus:ring-brand/50">
Save Changes
</button>
</div>
Animation Utilities
Tailwind v4 expands animation support considerably, making it easier to create polished interactions without custom CSS.
Transition Utilities
<!-- Smooth hover effect -->
<button class="bg-blue-600 hover:bg-blue-700
transform hover:scale-105
transition-all duration-200 ease-out
text-white px-6 py-3 rounded-lg">
Hover me
</button>
<!-- Transition specific properties -->
<div class="transition-colors duration-300 bg-gray-100 hover:bg-blue-100">
Color transition only
</div>
Built-in Animations
<!-- Spin animation for loading indicators -->
<svg class="animate-spin h-5 w-5 text-white" viewBox="0 0 24 24">
<!-- spinner SVG -->
</svg>
<!-- Pulse animation -->
<div class="animate-pulse bg-gray-200 rounded h-4 w-3/4"></div>
<!-- Bounce -->
<div class="animate-bounce">Scroll down</div>
Custom Animations with @theme
@theme {
--animate-slide-in: slide-in 0.3s ease-out;
--animate-fade-up: fade-up 0.5s ease-out;
}
@keyframes slide-in {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
@keyframes fade-up {
from {
opacity: 0;
transform: translateY(1rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
<div class="animate-slide-in">Slides in from the left</div>
<div class="animate-fade-up">Fades up into view</div>
Migrating from Tailwind v3 to v4
The migration from v3 to v4 requires some effort, but the Tailwind team provides a codemod tool that handles most changes automatically.
Running the Upgrade Tool
npx @tailwindcss/upgrade
This tool will scan your project and automatically convert most v3 patterns to v4 equivalents. It handles renaming utilities, migrating config, and updating imports.
Key Migration Changes
| v3 | v4 | Notes |
|---|---|---|
tailwind.config.js | @theme in CSS | Config moves to CSS |
@tailwind base/components/utilities | @import "tailwindcss" | Single import |
bg-opacity-50 | bg-black/50 | Opacity modifier syntax |
text-opacity-75 | text-white/75 | Opacity modifier syntax |
decoration-clone | box-decoration-clone | Renamed |
flex-shrink-0 | shrink-0 | Simplified (already worked in v3) |
flex-grow | grow | Simplified |
overflow-clip | overflow-clip | Same |
content paths in config | Automatic detection | No config needed |
darkMode: 'class' in config | @variant dark (...) in CSS | CSS-based |
Manual Steps
After running the upgrade tool, review these areas manually:
- Custom plugins: v3 JavaScript plugins need to be rewritten as CSS using
@utilityand@variantdirectives. - Custom theme values: Move them from
tailwind.config.jsto@themeblocks in CSS. - Third-party plugins: Check that they have been updated for v4 compatibility.
Converting a v3 Plugin to v4
v3 plugin (JavaScript):
// v3: tailwind.config.js plugin
const plugin = require('tailwindcss/plugin');
module.exports = {
plugins: [
plugin(function({ addUtilities }) {
addUtilities({
'.text-balance': {
'text-wrap': 'balance',
},
});
}),
],
};
v4 equivalent (CSS):
/* v4: defined directly in CSS */
@utility text-balance {
text-wrap: balance;
}
Converting a v3 Custom Variant
v3 (JavaScript):
// v3
plugin(function({ addVariant }) {
addVariant('hocus', ['&:hover', '&:focus']);
});
v4 (CSS):
/* v4 */
@variant hocus (&:hover, &:focus);
Building a Complete Component
Let us put everything together and build a pricing card component that demonstrates v4 features:
<div class="@container max-w-sm mx-auto">
<div class="rounded-2xl border border-gray-200 dark:border-gray-800
bg-white dark:bg-gray-900
shadow-xl shadow-gray-900/5 dark:shadow-gray-950/50
p-8
transition-all duration-300
hover:shadow-2xl hover:-translate-y-1">
<h3 class="text-sm font-semibold text-brand uppercase tracking-wider">
Pro Plan
</h3>
<div class="mt-4 flex items-baseline gap-1">
<span class="text-5xl font-bold text-gray-900 dark:text-white">$29</span>
<span class="text-gray-500 dark:text-gray-400">/month</span>
</div>
<p class="mt-4 text-sm text-gray-600 dark:text-gray-400">
Everything you need to build and ship faster.
</p>
<ul class="mt-8 space-y-3 text-sm">
<li class="flex items-center gap-3 text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-brand shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Unlimited projects
</li>
<li class="flex items-center gap-3 text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-brand shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Priority support
</li>
<li class="flex items-center gap-3 text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-brand shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Advanced analytics
</li>
</ul>
<button class="mt-8 w-full rounded-lg bg-brand py-3 text-sm font-semibold text-white
hover:bg-brand-dark
focus:outline-none focus:ring-2 focus:ring-brand/50 focus:ring-offset-2
dark:focus:ring-offset-gray-900
transition-colors duration-200">
Get started
</button>
</div>
</div>
Conclusion
Tailwind CSS v4 is a major step forward for the framework. The move to CSS-first configuration makes projects simpler to set up and reason about. The Oxide engine eliminates build performance as a concern. And the new utilities, built on modern CSS features like container queries and OKLCH colors, give you more powerful tools while writing less custom CSS.
If you are starting a new project, there is no reason not to use v4. If you are maintaining a v3 project, the upgrade tool makes migration straightforward for most codebases. The community and ecosystem have fully embraced v4, and the developer experience is better than it has ever been.
Use our CSS to Tailwind Converter to quickly convert existing CSS.
Start experimenting with the new features, especially container queries and the @theme directive. They fundamentally change how you can approach component design, and once you adopt them, going back feels like a downgrade.