Tailwind CSS v4 réécrit entièrement le modèle de configuration. Plus de tailwind.config.js — la personnalisation du thème bascule dans le CSS avec la directive @theme, et le setup PostCSS devient radicalement plus simple. Pour les développeurs React, cela ouvre un pattern qui n'était pas vraiment praticable avant : mélanger de manière transparente les classes utilitaires Tailwind avec des propriétés CSS personnalisées pour la thématisation à l'exécution. Voici tout ce qu'il faut savoir pour construire des composants avec v4.
Ce qui a changé entre v3 et v4
Les changements majeurs concernent la façon de configurer Tailwind et le fonctionnement du pipeline de build :
| Aspect | v3 | v4 |
|--------|----|----|
| Fichier de configuration | tailwind.config.js | Pas de config JS — CSS uniquement |
| Personnalisation du thème | theme.extend en JS | Directive @theme en CSS |
| Plugin PostCSS | tailwindcss | @tailwindcss/postcss |
| Détection du contenu | Tableau content: [...] | Automatique (scan du projet) |
| Import CSS | @tailwind base/components/utilities | @import "tailwindcss" |
| Propriétés personnalisées | Manuelles avec la fonction theme() | Natives via @theme |
| Valeurs arbitraires | bg-[#ff0000] | Fonctionne toujours, inchangé |
La détection du contenu est désormais automatique — v4 scanne les fichiers du projet sans que vous ayez à lister des globs. Cela seul élimine une source fréquente de bugs "ma classe ne s'applique pas".
Setup PostCSS
Installez un seul package :
npm install -D @tailwindcss/postcss
Votre postcss.config.mjs :
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
C'est tout. autoprefixer n'est plus nécessaire — v4 gère les préfixes vendeurs en interne.
Dans votre fichier CSS global (app/globals.css) :
@import "tailwindcss";
Une seule ligne remplace les trois directives @tailwind de v3.
La directive @theme
Les tokens de design personnalisés vivent dans un bloc @theme dans votre CSS. Ces tokens deviennent simultanément des classes utilitaires Tailwind et des propriétés CSS personnalisées :
/* app/globals.css */
@import "tailwindcss";
@theme {
--color-brand: #818cf8;
--color-brand-hover: #6366f1;
--color-surface: #111111;
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
--radius-sm: 0.5rem;
--radius-md: 0.75rem;
--radius-lg: 1rem;
--radius-full: 9999px;
--spacing-section: 6rem;
}
Une fois définis dans @theme, vous pouvez utiliser ces tokens de deux façons :
// As Tailwind classes
<div className="bg-brand text-surface rounded-lg p-section" />
// As CSS custom properties in inline styles
<div style={{ background: "var(--color-brand)" }} />
Les deux sont valides. Le choix dépend de si vous avez besoin d'overrides à l'exécution.
Propriétés CSS personnalisées pour le multi-thème
Le vrai pouvoir de v4 est la thématisation à l'exécution. Les propriétés CSS personnalisées peuvent être surchargées à n'importe quel niveau dans l'arbre DOM — changez l'attribut data-theme sur un élément parent et tous ses enfants se mettent à jour instantanément, sans JavaScript et sans changement de classes :
/* Theme A — light */
[data-theme="light"] {
--color-background: #ffffff;
--color-foreground: #18181b;
--color-accent: #a3e635;
--color-accent-hover: #84cc16;
--color-border: #e4e4e7;
}
/* Theme B — dark */
[data-theme="dark"] {
--color-background: #09090b;
--color-foreground: #fafafa;
--color-accent: #818cf8;
--color-accent-hover: #6366f1;
--color-border: #27272a;
}
Changer de thème en React :
"use client";
import { useState } from "react";
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<"light" | "dark">("light");
return (
<div data-theme={theme}>
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Toggle theme
</button>
{children}
</div>
);
}
Tout composant utilisant var(--color-background) ou var(--color-accent) répond automatiquement au changement de thème.
Mélanger classes Tailwind et variables CSS — le bon pattern
L'erreur la plus fréquente lors de la migration vers v4 est de mélanger les couleurs statiques de Tailwind avec les tokens basés sur des variables CSS dans un même composant. Cela casse la thématisation :
// Wrong — mixes static colors with themed tokens
<button className="bg-indigo-500 text-white rounded-full px-6 py-3">
Click me
</button>
// Correct — uses only themed tokens
<button
style={{
background: "var(--color-accent)",
color: "var(--color-background)",
borderRadius: "var(--radius-full)",
padding: "0.75rem 1.5rem",
border: "none",
cursor: "pointer",
}}
>
Click me
</button>
Pour les utilitaires de layout et d'espacement qui n'ont pas besoin d'être thématisables, les classes Tailwind conviennent parfaitement :
// Layout classes — not theme-sensitive, use Tailwind
<section className="flex flex-col items-center gap-8 py-24">
{/* Content with themed colors */}
<h2 style={{ color: "var(--color-foreground)", fontWeight: 700 }}>
Section Heading
</h2>
<p style={{ color: "var(--color-foreground-muted)" }}>
Description text
</p>
</section>
Cette approche hybride vous donne l'ergonomie de Tailwind pour le layout et le dimensionnement, plus une thématisation à l'exécution complète pour les propriétés visuelles.
Les valeurs arbitraires fonctionnent toujours
v4 conserve la syntaxe des valeurs arbitraires [value] de v3 :
<div className="w-[calc(100%-2rem)] mt-[3.75rem] grid-cols-[1fr_2fr_1fr]" />
Vous pouvez aussi utiliser des variables CSS directement dans les valeurs arbitraires :
<div className="bg-[var(--color-accent)] text-[var(--color-background)]" />
C'est pratique quand vous avez besoin des préfixes responsives de Tailwind avec des valeurs de variables CSS :
<div className="p-4 md:p-[var(--container-padding-x)]" />
Exemple de composant : un bouton thématisé
Voici un composant bouton complet utilisant les patterns v4 :
// components/Button.tsx
interface ButtonProps {
children: React.ReactNode;
variant?: "primary" | "secondary" | "ghost";
size?: "sm" | "md" | "lg";
href?: string;
onClick?: () => void;
disabled?: boolean;
}
const sizeStyles = {
sm: { padding: "0.5rem 1rem", fontSize: "0.8125rem" },
md: { padding: "0.75rem 1.5rem", fontSize: "0.875rem" },
lg: { padding: "0.875rem 2rem", fontSize: "0.9375rem" },
};
const variantStyles = {
primary: {
background: "var(--color-accent)",
color: "var(--color-foreground)",
border: "none",
},
secondary: {
background: "transparent",
color: "var(--color-foreground)",
border: "1px solid var(--color-border)",
},
ghost: {
background: "transparent",
color: "var(--color-foreground-muted)",
border: "none",
},
};
export function Button({ children, variant = "primary", size = "md", href, onClick, disabled }: ButtonProps) {
const style = {
...sizeStyles[size],
...variantStyles[variant],
borderRadius: "var(--radius-full)",
fontWeight: 600,
cursor: disabled ? "not-allowed" : "pointer",
opacity: disabled ? 0.5 : 1,
transition: `all var(--duration-normal) var(--ease-out)`,
textDecoration: "none",
display: "inline-flex",
alignItems: "center",
gap: "0.5rem",
};
if (href) {
return <a href={href} style={style}>{children}</a>;
}
return (
<button onClick={onClick} disabled={disabled} style={style}>
{children}
</button>
);
}
Ce bouton fonctionne correctement sur les 7 thèmes d'Incubator parce qu'il lit depuis des variables CSS, pas des valeurs de couleurs codées en dur.
Migration de v3 vers v4
Les étapes principales pour migrer un projet existant :
- Remplacez le plugin PostCSS :
tailwindcss→@tailwindcss/postcss, supprimezautoprefixer - Remplacez les imports CSS : Trois directives
@tailwind→@import "tailwindcss" - Déplacez le thème personnalisé dans
@theme: Copiez les valeurs detailwind.config.js→@theme {}en CSS - Mettez à jour les utilitaires dépréciés :
bg-opacity-*→bg-black/50,ring-offset-*→ supprimé - Supprimez
tailwind.config.js: Ou gardez-le temporairement si vous avez besoin de rétrocompatibilité
Le guide de migration v4 sur tailwindcss.com couvre les cas limites, mais pour la plupart des projets la mise à jour prend moins d'une heure.
Voir v4 en action
Les 449 sections du catalogue Incubator sont toutes construites avec Tailwind CSS v4, en utilisant l'approche hybride décrite ci-dessus — utilitaires Tailwind pour le layout, propriétés CSS personnalisées pour la thématisation. Parcourez le catalogue pour voir les patterns v4 appliqués à des composants du monde réel dans tous les types de sections.