Tailwind CSS v4 Fundamentals (2025/2026)
Overview
Tailwind CSS v4.0 was released January 22, 2025, featuring a complete rewrite with a Rust-based engine, CSS-first configuration, and significant performance improvements.
Key Changes from v3
Feature v3 v4
Configuration JavaScript (tailwind.config.js) CSS-first (@theme directive)
Engine Node.js Rust (10x faster)
Color format hex/rgb OKLCH (perceptually uniform)
Plugins JS files @plugin directive
Custom utilities JS config @utility directive
PostCSS imports postcss-import Built-in
Autoprefixer Required Built-in
CSS nesting postcss-nested Built-in
Content detection Explicit config Automatic
Installation
Vite Projects (Recommended)
npm install -D tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [tailwindcss()]
})
PostCSS Projects
npm install -D tailwindcss @tailwindcss/postcss
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {}
}
}
CSS Entry Point
/ app.css - The only required CSS file /
@import "tailwindcss";
CSS-First Configuration
The @theme Directive
Replace tailwind.config.js with CSS-based configuration:
@import "tailwindcss";
@theme {
/ Colors using modern oklch /
--color-primary: oklch(0.6 0.2 250);
--color-secondary: oklch(0.7 0.15 180);
--color-accent: oklch(0.8 0.2 30);
/ Typography /
--font-display: "Satoshi", sans-serif;
--font-body: "Inter", sans-serif;
/ Custom spacing /
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--spacing-xl: 4rem;
/ Custom breakpoints /
--breakpoint-xs: 475px;
--breakpoint-3xl: 1920px;
}
Theme Variables Reference
Category Variable Pattern Example
Colors --color- --color-brand-500
Fonts --font- --font-heading
Spacing --spacing- --spacing-4
Breakpoints --breakpoint- --breakpoint-3xl
Radius --radius- --radius-lg
Shadows --shadow- --shadow-xl
Animations --animate- --animate-fade-in
Easing --ease- --ease-bounce
Disabling Defaults
@theme {
/ Start fresh - disable all default theme values /
--*: initial;
/ Define only what you need /
--spacing: 4px;
--font-body: Inter, sans-serif;
--color-primary: oklch(0.72 0.11 221.19);
--color-secondary: oklch(0.74 0.17 40.24);
}
Custom Utilities
Static Utilities
/ Define custom utility in CSS /
@utility content-auto {
content-visibility: auto;
}
@utility text-balance {
text-wrap: balance;
}
@utility scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
@utility scrollbar-hide::-webkit-scrollbar {
display: none;
}
Usage:
Long headline that should balance nicely
Functional Utilities
/ Utility that accepts values /
@utility tab-* {
tab-size: --value(integer);
}
@utility text-shadow-* {
text-shadow: 0 0 --value([length]) currentColor;
}
/ With theme reference /
@utility gap-safe- {
gap: max(--value(--spacing- ), env(safe-area-inset-bottom));
}
Usage:
Code with 4-space tabs
Glowing text
Safe area aware gap
Custom Variants
The @custom-variant Directive
/ Dark mode with selector /
@custom-variant dark (&:where(.dark, .dark *));
/ Custom state variants /
@custom-variant hocus (&:hover, &:focus);
@custom-variant group-hocus (:merge(.group):hover &, :merge(.group):focus &);
/ Data attribute variants /
@custom-variant data-loading (&[data-loading="true"]);
@custom-variant data-active (&[data-state="active"]);
/ Child selectors /
@custom-variant children (& > );
@custom-variant not-first (& > :not(:first-child));
Usage:
Hover or focus
Loading...
Loading Plugins
The @plugin Directive
@import "tailwindcss";
/ Load official plugins /
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/container-queries";
/ Load local plugin /
@plugin "./my-plugin.js";
Plugin with Options
@plugin "@tailwindcss/typography" {
className: wysiwyg;
}
@plugin "@tailwindcss/forms" {
strategy: class;
}
Using Prefixes
@import "tailwindcss" prefix(tw);
@theme {
/ Define without prefix /
--font-display: "Satoshi", sans-serif;
}
Content
Generated CSS variables include prefix:
:root {
--tw-font-display: "Satoshi", sans-serif;
}
CSS Variables in Code
Replace theme() with var()
/ v3 approach (deprecated) /
.old-way {
background-color: theme(colors.red.500);
}
/ v4 approach /
.new-way {
background-color: var(--color-red-500);
}
/ In media queries, use CSS variable names /
@media (width >= theme(--breakpoint-xl)) {
/ styles /
}
Core Utility Categories
Layout
Spacing
Typography
Colors
Sizing
Arbitrary Values
Important Modifier
Built-in Features (No Config Needed)
Feature v3 Requirement v4
@import handling postcss-import Built-in
Vendor prefixing autoprefixer Built-in
CSS nesting postcss-nested Built-in
Content detection content config Automatic
Layers
/* Use native CSS layers */
@layer base {
h1 {
@apply text-2xl font-bold;
}
}
@layer components {
.btn {
@apply px-4 py-2 rounded font-medium;
}
}
@layer utilities {
/* Custom utilities via @utility directive instead */
}
Best Practices (2025/2026)
1. Use OKLCH Colors for Design Systems
OKLCH provides perceptually uniform colors, better gradients, and wide gamut support:
@theme {
/* OKLCH format: oklch(lightness chroma hue) */
/* Lightness: 0-1, Chroma: 0-0.4, Hue: 0-360 */
/* Primary palette - adjust L for shades */
--color-primary-50: oklch(0.97 0.02 250);
--color-primary-100: oklch(0.93 0.04 250);
--color-primary-500: oklch(0.55 0.2 250); /* Base */
--color-primary-600: oklch(0.48 0.2 250);
--color-primary-900: oklch(0.27 0.12 250);
/* Semantic colors */
--color-success: oklch(0.6 0.15 145);
--color-warning: oklch(0.75 0.15 65);
--color-error: oklch(0.55 0.2 25);
}
2. Implement Fluid Typography
Smooth scaling without breakpoint jumps:
@theme {
/* Fluid type scale using clamp() */
/* clamp(min, preferred, max) */
--text-fluid-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
--text-fluid-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem);
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--text-fluid-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem);
--text-fluid-xl: clamp(1.25rem, 1rem + 1.25vw, 1.5rem);
--text-fluid-2xl: clamp(1.5rem, 1.1rem + 2vw, 2rem);
--text-fluid-3xl: clamp(1.875rem, 1.2rem + 3.375vw, 2.5rem);
--text-fluid-4xl: clamp(2.25rem, 1rem + 6.25vw, 3.5rem);
}
Important: Always combine vw with rem for accessibility (respects zoom).
3. Fluid Spacing System
@theme {
/* Fluid spacing that scales with viewport */
--spacing-fluid-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem);
--spacing-fluid-md: clamp(1rem, 0.75rem + 1.25vw, 2rem);
--spacing-fluid-lg: clamp(2rem, 1rem + 3vw, 4rem);
--spacing-fluid-section: clamp(4rem, 2rem + 8vw, 8rem);
}
4. Organize Theme by Category
@theme {
/* === Colors === */
--color-primary: oklch(0.6 0.2 250);
--color-secondary: oklch(0.7 0.15 180);
--color-success: oklch(0.6 0.15 145);
--color-error: oklch(0.55 0.2 25);
/* === Typography === */
--font-sans: 'Inter Variable', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
/* === Fluid Typography === */
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
--text-fluid-lg: clamp(1.25rem, 1rem + 1.25vw, 2rem);
/* === Spacing === */
--spacing-page: 2rem;
--spacing-fluid-section: clamp(4rem, 2rem + 8vw, 8rem);
/* === Border Radius === */
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
/* === Shadows === */
--shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05);
--shadow-md: 0 4px 6px oklch(0 0 0 / 0.07);
/* === Easing === */
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
--ease-snappy: cubic-bezier(0.2, 0, 0, 1);
}
5. Keep @utility Definitions Simple
/* Good - single purpose utilities */
@utility truncate-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@utility text-balance {
text-wrap: balance;
}
@utility content-auto {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
}
/* Safe area utilities for notched devices */
@utility safe-area-pb {
padding-bottom: env(safe-area-inset-bottom);
}
@utility safe-area-pt {
padding-top: env(safe-area-inset-top);
}
/* Avoid - too complex, use components instead */
@utility card-fancy {
/* Too many properties - use @layer components */
}
6. Mobile-First Class Ordering
Always structure responsive classes progressively:
Content
7. Accessible Interactive Elements
Button Text
Common Migration Issues
Border Color Default
/* v3: border used gray-200 by default */
/* v4: border uses currentColor */
/* Fix: explicitly set color */
@theme {
--default-border-color: var(--color-gray-200);
}
Ring Default
/* v3: ring was 3px blue-500 */
/* v4: ring is 1px currentColor */
/* Fix: restore v3 behavior */
@theme {
--default-ring-width: 3px;
--default-ring-color: var(--color-blue-500);
}
Button Cursor
/* v4: buttons use cursor: default */
/* Fix: add pointer globally if needed */
button {
cursor: pointer;
}
← 返回排行榜