Changer le thème

Tailwind CSS v4 : nouveautés, performance, configuration et guide de migration

Easton editorial illustration: responsive layout folding board

35 millisecondes. C’est le temps d’un build incrémental Tailwind v3. En v4, la même opération prend 192 microsecondes. Pas des millisecondes — des microsecondes.

La première fois que j’ai vu ce chiffre, j’étais sceptique. Qui ne sait pas écrire du marketing ? Mais après avoir lancé une migration et vu le HMR passer de 340 ms à 12 ms, j’ai compris : cette fois, Tailwind ne plaisante pas.

C’est le changement concret apporté par Oxide, le moteur réécrit en Rust. Pas un « un peu plus rapide » subjectif — plutôt modifier un padding et voir la page se rafraîchir avant d’avoir cligné des yeux. Tailwind v4 ne se contente pas de changer de moteur : il refond la configuration (du JS au CSS), l’installation (zéro config) et la syntaxe des utilitaires (modificateurs d’opacité, Container Queries, 3D Transforms…).

Cet article détaille ces évolutions et vous donne une checklist de migration prête à l’emploi.

Moteur Oxide — pourquoi v4 est si rapide ?

Vous connaissez ce scénario : vous changez une couleur, vous sauvegardez, puis vous attendez deux ou trois secondes avant de voir le résultat ? Sur un gros projet, le build incrémental de Tailwind v3 peut stresser — surtout à l’approche d’une deadline.

Le moteur Oxide de v4 vise exactement ce point. L’équipe Tailwind n’a pas bricolé l’ancien moteur JS : elle a réécrit tout le compilateur en Rust from scratch. Un pari audacieux, avec des gains mesurables.

De combien les performances augmentent-elles ?

Les benchmarks officiels sur le projet Catalyst sont parlants :

Scénariov3.4v4.0Gain
Build complet378ms100ms3,78×
Build incrémental (CSS modifié)44ms5ms8,8×
Build incrémental (sans changement CSS)35ms192µs182×

Ce dernier chiffre est le plus frappant. Quand vous ne modifiez que la structure HTML sans nouvelles classes CSS, v4 tombe au niveau microseconde — une latence imperceptible.

Données d’un projet en production (500+ composants) :

Indicateurv3.4v4.0Évolution
Build à froid12,3s1,8s−85 %
Démarrage serveur dev4,2s0,8s−81 %
Mise à jour HMR340ms12ms−96 %
Taille CSS prod48KB31KB−35 %
Mémoire180MB45MB−75 %
96 %
Gain vitesse HMR

Passer de 340 ms à 12 ms en HMR transforme l’expérience de dev. Avant, chaque modification de style imposait une pause visible ; maintenant, c’est quasi instantané.

Qu’est-ce qu’Oxide fait bien ?

Le cœur d’Oxide : Rust + Lightning CSS. Les performances de Rust sont connues, mais le vrai levier est architectural :

Chaîne d’outils unifiée. À l’ère v3, Tailwind dépendait de PostCSS et de autoprefixer, cssnano, etc. v4 intègre tout via Lightning CSS. Moins d’étapes, plus de vitesse.

Détection intelligente du contenu. Avant, il fallait remplir content dans tailwind.config.js. v4 lit .gitignore et le graphe de modules pour découvrir les fichiers à scanner. Moins de config, plus de rapidité.

CSS natif. v4 exploite @layer, @property, color-mix() et d’autres fonctionnalités modernes prises en charge nativement par le navigateur, sans transformation lourde au build.

Honnêtement, vous n’avez pas besoin de maîtriser chaque détail technique. L’essentiel : builds plus rapides, moins de configuration, meilleure expérience de développement.

Configuration CSS-first — adieu tailwind.config.js

C’est le changement le plus marquant de v4, et la partie la plus coûteuse à migrer.

Avant, on écrivait la config dans tailwind.config.js ; maintenant, tout va dans le CSS via @theme. Au début, c’était déroutant — des années de config JS, puis des variables CSS. Après quelques semaines, ça colle mieux à la logique CSS.

Migration de config : Before & After

Exemple minimal — une couleur primaire personnalisée :

// v3: tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: '#3b82f6',
      },
    },
  },
}

En v4, tout part dans le CSS :

/* v4: app.css */
@import "tailwindcss";

@theme {
  --color-primary: #3b82f6;
}

Vous avez remarqué : primary devient --color-primary. v4 impose des préfixes stricts.

Table de correspondance des variables

Config v3Préfixe variable v4Exemple
colors—color-*—color-primary: #3b82f6
spacing—spacing-*—spacing-128: 32rem
fontSize—text-*—text-xs: 0.75rem
fontFamily—font-*—font-sans: “Inter”
borderRadius—radius-*—radius-lg: 0.5rem
screens—breakpoint-*—breakpoint-md: 768px
boxShadow—shadow-*—shadow-card: 0 4px 12px rgba(0,0,0,0.1)
animation—animate-*—animate-spin: spin 1s linear infinite

Ce système de préfixes semble lourd au départ, mais il évite les devinettes : pour une taille de texte, le préfixe est toujours --text-.

Exemple de config plus complexe

Config v3 typique :

// v3: tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          light: '#f0f9ff',
          DEFAULT: '#0ea5e9',
          dark: '#0369a1',
        },
      },
      fontFamily: {
        display: ['Cal Sans', 'sans-serif'],
      },
      animation: {
        'fade-in': 'fadeIn 0.5s ease-out',
      },
    },
  },
  plugins: [
    require('@tailwindcss/typography'),
  ],
}

Migration v4 :

/* v4: app.css */
@import "tailwindcss";

@theme {
  /* Couleurs */
  --color-brand-light: #f0f9ff;
  --color-brand: #0ea5e9;
  --color-brand-dark: #0369a1;

  /* Polices */
  --font-display: "Cal Sans", sans-serif;

  /* Animations */
  --animate-fade-in: fadeIn 0.5s ease-out;
}

/* Plugins */
@plugin "@tailwindcss/typography";

Points clés :

  1. Couleurs aplaties. v3 acceptait brand.light ; v4 exige --color-brand-light
  2. Plugins via @plugin. Plus de require en JS
  3. Plus de suffixe DEFAULT. La couleur par défaut de brand devient --color-brand

Configuration du mode sombre

En v3 :

// v3
module.exports = {
  darkMode: 'class', // ou 'media'
}

v4 utilise media par défaut (suit le système). Pour class, ajoutez une ligne en CSS :

/* v4 */
@import "tailwindcss";
@variant dark (&:where(.dark, .dark *));

Quand l’élément ou un parent a la classe .dark, les styles sombres s’appliquent.

Configuration de la détection de contenu

Avant, il fallait lister les fichiers à scanner :

// v3
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './public/index.html',
  ],
}

v4 lit .gitignore, ignore les dossiers exclus, puis scanne le projet. Structure atypique ? Utilisez @source :

/* v4 */
@import "tailwindcss";
@source "../node_modules/my-ui-lib";

Le principal avantage CSS-first : toute la config visuelle dans un seul fichier CSS, sans alterner JS et CSS. L’inconvénient : une période d’adaptation pour ceux habitués au JS.

Installation et intégration — expérience zéro config

Avec Tailwind v3 : trois paquets, un fichier de config, PostCSS, tableau content… Pas terrible, mais répétitif à chaque nouveau projet.

v4 réduit tout cela au minimum.

Installation minimale

Avec Vite, deux étapes :

# 1. Installation
npm install tailwindcss @tailwindcss/vite

# 2. Une ligne dans vite.config.js
import tailwindcss from '@tailwindcss/vite'

export default {
  plugins: [tailwindcss()],
}

Puis une importation dans votre CSS :

/* app.css ou index.css */
@import "tailwindcss";

C’est tout. Pas de tailwind.config.js, pas de postcss.config.js, pas de content. Prêt à l’emploi.

Trois modes d’intégration

Intégration Vite (recommandée) :

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'

export default {
  plugins: [tailwindcss()],
}

Intégration PostCSS :

npm install tailwindcss @tailwindcss/postcss
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

CLI :

npx tailwindcss -i input.css -o output.css --watch

La plupart des projets modernes suffisent avec Vite. PostCSS convient aux migrations legacy ; le CLI aux workflows sans build.

Principe de la détection automatique

v4 n’exige plus content. Comment ça marche ?

Il lit .gitignore, exclut node_modules, dist, etc., puis recherche les classes Tailwind dans les fichiers restants.

Prérequis : structure Node.js standard. Fichiers templates hors arborescence habituelle ?

@import "tailwindcss";
@source "../templates";  /* chemin de scan manuel */

Autre avantage : nouveaux fichiers sans toucher la config. Avant, chaque composant pouvait imposer une mise à jour de content (sauf glob **/*). Plus besoin.

Breaking changes et checklist de migration

Cœur de la migration. Pas de panique : la plupart des changements suivent une logique, et un outil automatique existe.

Évolution des modificateurs d’opacité

Changement le plus impactant. En v3 :

<!-- v3 -->
<div class="bg-blue-500 bg-opacity-50">...</div>

v4 intègre l’opacité dans la couleur :

<!-- v4 -->
<div class="bg-blue-500/50">...</div>

Toutes les propriétés couleur supportent cette syntaxe :

<!-- Opacité texte -->
<p class="text-gray-900/75">...</p>

<!-- Opacité bordure -->
<div class="border-red-500/30">...</div>

Les classes bg-opacity-* ? Supprimez-les. v4 ne les supporte plus.

Classes utilitaires renommées

Quelques renommages pour simplifier ou clarifier :

Classe v3Classe v4Note
flex-growgrowNom simplifié
flex-grow-*grow-*Nom simplifié
flex-shrinkshrinkNom simplifié
flex-shrink-*shrink-*Nom simplifié
overflow-ellipsistext-ellipsisReclassement
decoration-slicebox-decoration-sliceReclassement
shadow-smshadow-xsRenommage taille
shadowshadow-smRenommage taille
rounded-smrounded-xsRenommage taille
roundedrounded-smRenommage taille
outline-noneoutline-hiddenChangement sémantique

Attention shadow et rounded : l’ancien shadow devient shadow-sm, l’ancien shadow-sm devient shadow-xs. Ajustement pour harmoniser les échelles de taille.

Changements de valeurs par défaut

Quelques défauts modifiés peuvent créer des écarts visuels :

Couleur border par défaut : v3 gray-200, v4 currentColor. La bordure suit la couleur du texte.

<!-- v3 : bordure grise -->
<div class="border text-blue-500">Bordure gray-200</div>

<!-- v4 : bordure suit le texte -->
<div class="border text-blue-500">Bordure blue-500</div>

Valeurs ring par défaut : v3 3px blue-500 ; v4 1px currentColor.

<!-- v3 : ring bleu 3px -->
<button class="ring">...</button>

<!-- v4 : ring currentColor 1px -->
<button class="ring">...</button>

<!-- Effet v3 -->
<button class="ring-3 ring-blue-500">...</button>

Checklist de migration complète

Dans l’ordre :

  1. Mettre à jour les dépendances

    npm install tailwindcss@latest @tailwindcss/vite@latest
  2. Lancer l’outil automatique

    npx @tailwindcss/upgrade

    Convertit la plupart des syntaxes : directives @tailwind, opacité, classes renommées, etc.

  3. Convertir le CSS d’entrée

    /* v3 */
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
    /* v4 */
    @import "tailwindcss";
  4. Migrer la config : déplacer tailwind.config.js vers @theme en CSS.

  5. Mettre à jour les plugins : syntaxe @plugin.

    @plugin "@tailwindcss/typography";
  6. Vérifier l’opacité : rechercher bg-opacity, text-opacity, border-opacity, remplacer par la nouvelle syntaxe.

  7. Vérifier les renommages : shadow-*, rounded-*, flex-grow-*, flex-shrink-*.

  8. Vérifier les défauts : couleurs border et styles ring.

  9. Tests visuels : lancer vos tests de régression.

L’outil automatique couvre ~80 % ; les 20 % restants demandent une revue humaine, surtout pour les changements de valeurs par défaut que l’outil ne peut pas deviner.

Nouveautés — Container Queries, 3D Transforms et autres

Au-delà performance et config, v4 apporte des fonctionnalités utiles au quotidien.

Container Queries intégrées

Avant, un plugin était nécessaire ; maintenant c’est natif :

<!-- Définir le conteneur -->
<div class="@container">
  <!-- Réponse à la largeur du conteneur -->
  <div class="@md:grid-cols-2 @lg:grid-cols-3">
    ...
  </div>
</div>

@container équivaut à container-type: inline-size ; @md: est un breakpoint de container query. Syntaxe proche de md:, avec un @ devant.

Idéal pour les bibliothèques de composants : le style s’adapte au parent, pas seulement à la largeur d’écran.

Utilitaires 3D Transform

Nouvelle famille de transformations 3D :

<!-- Perspective 3D -->
<div class="perspective-distant">
  <!-- Rotation axe X -->
  <div class="rotate-x-45">...</div>
</div>

<!-- Rotation axe Y -->
<div class="rotate-y-12">...</div>

<!-- Échelle axe Z -->
<div class="scale-z-150">...</div>

Classes disponibles : rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, perspective-*, translate-z-*, etc. Cartes flip, menus 3D — bien plus simple.

Variante @starting-style

S’appuie sur @starting-style CSS pour le rendu initial :

<!-- Apparition : transparent → opaque -->
<div class="starting:opacity-0 opacity-100 transition-opacity">
  ...
</div>

Animation d’entrée sans JavaScript. Avant, il fallait animate-fade-in custom ; maintenant une classe suffit.

Variante not-*

Support de :not() :

<!-- Tous les enfants sauf le dernier -->
<li class="not-last:mb-4">...</li>

<!-- Boutons non disabled -->
<button class="not-disabled:opacity-100">...</button>

Plus intuitif que l’inversion last:mb-0.

Gradient API étendue

Gradients renforcés en v4 :

<!-- Dégradé conique -->
<div class="bg-conic/from-red-500 via-yellow-500 to-blue-500">...</div>

<!-- Dégradé radial -->
<div class="bg-radial from-white to-transparent">...</div>

<!-- Mode d'interpolation -->
<div class="bg-linear-to-r from-blue-500 to-purple-500 via-oklch">...</div>

via-oklch améliore les transitions, surtout lors des conversions d’espace colorimétrique.

Conclusion

Faut-il migrer ?

Si le projet est en développement actif, oui. HMR de centaines de ms à une dizaine — du temps gagné chaque jour. CSS plus léger, moins de mémoire : particulièrement rentable sur les gros codebases.

Le coût principal : conversion de config et renommages de classes. Heureusement, npx @tailwindcss/upgrade automatise l’essentiel. Sur un projet moyen (200+ composants), comptez une demi-journée avec tests.

Nouveau projet ? Partez directement sur v4. Zéro config, détection auto, CSS-first — Tailwind n’a jamais été aussi simple.

Compatibilité navigateur : Safari 16.4+, Chrome 111+, Firefox 128+. Cible anciens navigateurs ? Attendez encore.

Recommandations :

Guide de migration Tailwind CSS v4

Étapes complètes pour passer de Tailwind v3 à v4

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Mettre à jour les dépendances

    Exécutez la commande npm pour installer les dernières versions :

    ```bash
    npm install tailwindcss@latest @tailwindcss/vite@latest
    ```

    Avec l'intégration PostCSS, installez :
    ```bash
    npm install tailwindcss@latest @tailwindcss/postcss@latest
    ```
  2. 2

    Step 2: Lancer l'outil de migration automatique

    Tailwind fournit un outil de migration en une commande :

    ```bash
    npx @tailwindcss/upgrade
    ```

    Cet outil gère automatiquement :
    • conversion des directives @tailwind en @import "tailwindcss"
    • opacité bg-opacity-* vers la syntaxe /50
    • classes utilitaires renommées (shadow-sm → shadow-xs, etc.)
    • conversion du fichier de config au format CSS @theme
  3. 3

    Step 3: Convertir le fichier CSS d'entrée

    Remplacez les trois directives @tailwind par un seul @import :

    ```css
    /* Supprimez ceci */
    @tailwind base;
    @tailwind components;
    @tailwind utilities;

    /* Remplacez par */
    @import "tailwindcss";
    ```
  4. 4

    Step 4: Migrer la config personnalisée vers le CSS

    Déplacez la config thème de tailwind.config.js dans le fichier CSS :

    ```css
    @import "tailwindcss";

    @theme {
    /* Couleurs */
    --color-brand: #0ea5e9;

    /* Polices */
    --font-display: "Cal Sans", sans-serif;

    /* Animations */
    --animate-fade-in: fadeIn 0.5s ease-out;
    }
    ```

    Règles de nommage : colors → --color-*, fontSize → --text-*
  5. 5

    Step 5: Mettre à jour l'import des plugins

    Les plugins JS passent par la directive @plugin :

    ```css
    /* Ancienne méthode : dans tailwind.config.js */
    // plugins: [require('@tailwindcss/typography')]

    /* Nouvelle méthode : dans le fichier CSS */
    @plugin "@tailwindcss/typography";
    ```
  6. 6

    Step 6: Vérifier les changements de valeurs par défaut

    Deux changements importants :

    • **Couleur border** : de gray-200 à currentColor
    - Pour retrouver la bordure grise, ajoutez explicitement border-gray-200

    • **Valeurs par défaut ring** : de 3px blue-500 à 1px currentColor
    - Pour l'effet v3, utilisez ring-3 ring-blue-500
  7. 7

    Step 7: Tester et corriger les styles

    Lancez le serveur de dev pour vérifier les changements visuels :

    ```bash
    npm run dev
    ```

    Points à contrôler :
    • styles liés à l'opacité
    • tailles shadow et rounded conformes aux attentes
    • couleurs de bordure alignées avec la maquette
    • tests de régression visuelle du projet (si disponibles)

FAQ

Quelle est la plus grande différence entre Tailwind CSS v4 et v3 ?
Trois changements majeurs : le moteur Oxide réécrit en Rust, HMR 96 % plus rapide ; la config passe du JS au CSS avec @theme ; installation simplifiée, 2 étapes pour un projet Vite.
Combien de temps prend la migration vers Tailwind v4 ?
Environ une demi-journée pour un projet moyen (200+ composants). L'outil automatique couvre 80 % du travail ; les 20 % restants demandent une revue manuelle des valeurs par défaut et des configs spéciales.
Quelles exigences de compatibilité navigateur pour v4 ?
Safari 16.4+, Chrome 111+, Firefox 128+, car v4 s'appuie sur @layer, @property, color-mix(), etc. Les projets ciblant d'anciens navigateurs devraient attendre.
Que gère l'outil de migration automatique ?
Conversion @tailwind, syntaxe opacité (bg-opacity-50 → /50), classes renommées (shadow-sm → shadow-xs), config JS → CSS @theme. Il ne corrige pas les écarts visuels dus aux nouvelles valeurs par défaut.
Faut-il encore configurer le tableau content en v4 ?
Non. v4 lit .gitignore pour exclure les dossiers inutiles, puis scanne les classes Tailwind du projet. Cas particuliers : directive @source pour ajouter des chemins.
Styles incohérents après upgrade v3 — que faire ?
Vérifiez trois changements de défaut : border gray-200 → currentColor, ring 3px blue-500 → 1px currentColor, ajustements shadow et rounded. Ajoutez les classes explicites sur les éléments concernés.
Quelles nouveautés v4 méritent l'attention ?
Container Queries intégrées (@container), utilitaires 3D Transform (rotate-x/y/z, perspective-*), variante @starting-style pour animations d'entrée, variante not-*, Gradient API étendue (conic, radial, interpolation oklch).

10 min de lecture · Publié le: 25 mars 2026 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog