Développement Web

Comprendre les nouveautés Tailwind v4

13 min de lecture

Ce que vous saurez faire à la fin

  1. Installer Tailwind CSS v4 avec son nouveau moteur Oxide écrit en Rust, 5 à 10 fois plus rapide que la v3.
  2. Configurer un design system cohérent (couleurs, typographie, espacements) en CSS pur, sans tailwind.config.js.
  3. Construire des composants réutilisables (boutons, cards, formulaires) adaptés à une PME sénégalaise avec mode sombre.
  4. Optimiser le CSS de production en passant de 3 Mo à 12 Ko grâce au tree-shaking automatique.
  5. Intégrer Tailwind v4 dans Next.js 15, Vite, Astro ou WordPress sans casser l’existant.

Durée : 3h30. Pré-requis : HTML/CSS de base, npm, un projet web ou la volonté d’en créer un. VS Code recommandé avec extension Tailwind CSS IntelliSense. Coût : 0 FCFA.

Étape 1 — Comprendre les nouveautés Tailwind v4

Tailwind v4, sortie en début 2025 et désormais stable, marque la plus grande refonte depuis la création du framework. Trois changements majeurs : moteur Oxide en Rust (10x plus rapide), configuration en CSS pur (fini le JavaScript), et détection automatique des classes (plus besoin de content dans la config).

Performance benchmarks (projet 200 composants) :
Tailwind v3 (JIT)  : 380 ms par build
Tailwind v4 (Oxide) : 38 ms par build (10x plus rapide)

Bundle CSS de production :
v3 avec purge : 18 Ko gzip
v4 (auto)     : 11 Ko gzip (tree-shaking plus agressif)

Nouveautés syntaxe :
- @theme dans le CSS au lieu de tailwind.config.js
- Variables CSS natives (var(--color-emerald-500))
- @utility pour créer ses propres classes
- Container queries natives

Étape 2 — Installation dans un projet Vite

npm create vite@latest mon-site -- --template vanilla
cd mon-site
npm install
npm install -D tailwindcss @tailwindcss/vite
// vite.config.js
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [tailwindcss()]
});
/* src/style.css */
@import "tailwindcss";

C’est tout. Plus de tailwind.config.js, plus de postcss.config.js. Une seule ligne d’import et le moteur Oxide scanne automatiquement vos fichiers HTML, JSX, Vue, Svelte, Astro pour générer uniquement les classes utilisées.

Étape 3 — Configuration via @theme

/* src/style.css */
@import "tailwindcss";

@theme {
  /* Palette de marque PME Sénégal */
  --color-marque-50: #f0fdf4;
  --color-marque-500: #00853f; /* vert drapeau Sénégal */
  --color-marque-600: #006b32;
  --color-marque-900: #052e16;

  --color-accent-500: #fdef42; /* jaune drapeau Sénégal */
  --color-accent-700: #c4b836;

  /* Typographie locale-friendly */
  --font-sans: "Inter", "Noto Sans", system-ui, sans-serif;
  --font-display: "Outfit", "Inter", sans-serif;

  /* Breakpoints adaptés mobile-first africain */
  --breakpoint-xs: 360px;  /* Tecno, Itel petits écrans */
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;

  /* Rayons de bordure */
  --radius-pill: 9999px;
  --radius-card: 1rem;
}

Toutes les valeurs définies dans @theme deviennent automatiquement utilisables comme classes : bg-marque-500, text-accent-700, font-display, max-xs, rounded-card.

Étape 4 — Premier composant : carte produit

<article class="rounded-card bg-white shadow-md transition hover:shadow-xl
                dark:bg-zinc-900 dark:shadow-zinc-800/50">
  <img
    src="/produits/riz-tilda-5kg.webp"
    alt="Riz Tilda 5 kg"
    class="aspect-square w-full rounded-t-card object-cover"
    loading="lazy"
  />
  <div class="p-4 space-y-2">
    <h3 class="font-display text-lg font-semibold text-zinc-900
              dark:text-zinc-100">
      Riz Tilda Basmati 5 kg
    </h3>
    <p class="text-sm text-zinc-600 dark:text-zinc-400">
      Riz long grain importé d'Inde, parfumé.
    </p>
    <div class="flex items-center justify-between pt-2">
      <span class="text-xl font-bold text-marque-600">12 500 FCFA</span>
      <button class="rounded-pill bg-marque-500 px-4 py-2 text-sm
                    font-medium text-white transition
                    hover:bg-marque-600 active:scale-95">
        Ajouter
      </button>
    </div>
  </div>
</article>

Étape 5 — Mode sombre automatique

/* Activer la stratégie 'class' pour basculer manuellement */
@import "tailwindcss";

@variant dark (&:where(.dark, .dark *));
<!-- Bouton bascule mode sombre -->
<button onclick="document.documentElement.classList.toggle('dark')"
        class="fixed top-4 right-4 rounded-full bg-zinc-200
               p-2 dark:bg-zinc-800">
  Basculer
</button>

<!-- Sauvegarder le choix -->
<script>
  const pref = localStorage.getItem('theme');
  if (pref === 'dark' || (!pref &&
      window.matchMedia('(prefers-color-scheme: dark)').matches)) {
    document.documentElement.classList.add('dark');
  }
</script>

Étape 6 — Variants modernes : has, not, peer

<!-- Style conditionnel basé sur les enfants (has) -->
<form class="rounded-lg border p-4 has-[input:invalid]:border-red-500
             has-[input:valid]:border-green-500">
  <input type="email" required class="w-full rounded border px-3 py-2" />
</form>

<!-- Inverser une condition (not) -->
<div class="not-hover:opacity-70 hover:opacity-100 transition">
  Survolez pour rendre lisible
</div>

<!-- Peer : réagir à l'état d'un sibling -->
<label class="block">
  <input type="checkbox" class="peer sr-only" />
  <span class="block rounded border-2 border-zinc-300 p-4
              peer-checked:border-marque-500 peer-checked:bg-marque-50
              cursor-pointer transition">
    Livraison Wave (gratuite)
  </span>
</label>

Étape 7 — Container queries natives

<!-- Le composant s'adapte à la largeur de SON parent, pas du viewport -->
<div class="@container">
  <div class="grid grid-cols-1 gap-4
              @md:grid-cols-2 @lg:grid-cols-3">
    <article>Produit 1</article>
    <article>Produit 2</article>
    <article>Produit 3</article>
  </div>
</div>

Avant : un composant carte ne pouvait pas savoir s’il était dans une sidebar étroite ou en pleine largeur. Avec @container, il s’adapte automatiquement. Indispensable pour des composants réutilisables dans plusieurs contextes (dashboard, page produit, modal).

Étape 8 — Créer ses propres utilities

@import "tailwindcss";

/* Composer une classe métier */
@utility btn-wave {
  @apply rounded-pill bg-marque-500 px-6 py-3 text-white
         font-medium transition hover:bg-marque-600
         active:scale-95 disabled:opacity-50;
}

@utility text-balance {
  text-wrap: balance;
}

/* Utility avec valeurs dynamiques */
@utility tab-* {
  tab-size: --value(integer);
}
/* Utilisation : tab-2, tab-4, tab-8 */

Étape 9 — Formulaires accessibles

<form class="mx-auto max-w-md space-y-4 p-6">
  <div>
    <label for="nom" class="block text-sm font-medium text-zinc-700
                            dark:text-zinc-300">
      Nom complet
    </label>
    <input
      id="nom"
      type="text"
      required
      class="mt-1 block w-full rounded-lg border-zinc-300 shadow-sm
             focus:border-marque-500 focus:ring-2 focus:ring-marque-500/20
             dark:bg-zinc-800 dark:border-zinc-700 dark:text-white"
    />
  </div>

  <div>
    <label for="tel" class="block text-sm font-medium text-zinc-700
                            dark:text-zinc-300">
      Téléphone Wave
    </label>
    <input
      id="tel"
      type="tel"
      pattern="\+221[0-9]{9}"
      placeholder="+221 77 123 45 67"
      class="mt-1 block w-full rounded-lg border-zinc-300 shadow-sm
             invalid:border-red-300 invalid:focus:ring-red-200
             dark:bg-zinc-800 dark:border-zinc-700"
    />
  </div>

  <button type="submit" class="btn-wave w-full">
    Valider la commande
  </button>
</form>

Étape 10 — Animations fluides

@import "tailwindcss";

@theme {
  --animate-pulse-soft: pulse-soft 2s ease-in-out infinite;
  --animate-slide-up: slide-up 300ms ease-out;
}

@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

@keyframes slide-up {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
<div class="animate-slide-up rounded-card bg-white p-4">
  Notification : Votre commande est confirmée
</div>

<span class="animate-pulse-soft rounded-pill bg-emerald-100
            px-3 py-1 text-emerald-700">
  En direct
</span>

Étape 11 — Intégration dans Next.js 15

cd mon-app-next
npm install -D tailwindcss @tailwindcss/postcss
// postcss.config.mjs
export default {
  plugins: { '@tailwindcss/postcss': {} }
};
/* app/globals.css */
@import "tailwindcss";

@theme {
  --color-marque-500: #00853f;
}
// app/layout.tsx
import './globals.css';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="fr-SN">
      <body className="bg-white text-zinc-900 antialiased">
        {children}
      </body>
    </html>
  );
}

Étape 12 — Intégration WordPress

cd wp-content/themes/mon-theme
npm init -y
npm install -D tailwindcss @tailwindcss/cli
/* assets/css/source.css */
@import "tailwindcss";

@source "../../**/*.php";
@source "../../**/*.html";

@theme {
  --color-marque-500: #00853f;
}
// package.json scripts
{
  "scripts": {
    "build:css": "tailwindcss -i assets/css/source.css -o assets/css/style.css --minify",
    "watch:css": "tailwindcss -i assets/css/source.css -o assets/css/style.css --watch"
  }
}
<?php // functions.php
function enqueue_tailwind() {
  wp_enqueue_style('tailwind',
    get_template_directory_uri() . '/assets/css/style.css',
    [], filemtime(get_template_directory() . '/assets/css/style.css'));
}
add_action('wp_enqueue_scripts', 'enqueue_tailwind');

Étape 13 — Optimisation de production

npm run build
# Inspecter la taille du CSS final
ls -lh dist/assets/*.css

# Audit avec PurgeCSS-like (déjà fait par Tailwind)
# Vérifier qu'aucune classe non utilisée n'est présente

# Compression Brotli côté serveur
# Sur Nginx :
# brotli on;
# brotli_types text/css application/javascript;

Étape 14 — Plugin VS Code et workflow

Extensions VS Code essentielles :
1. Tailwind CSS IntelliSense (autocomplétion + preview couleurs)
2. Headwind (tri automatique des classes)
3. PostCSS Language Support

Réglage settings.json :
{
  "tailwindCSS.experimental.classRegex": [
    ["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
    ["cn\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
  ],
  "editor.quickSuggestions": { "strings": "on" }
}

Erreurs fréquentes

  • Classes non détectées : Tailwind v4 scanne par défaut tout sauf node_modules et .git. Pour inclure d’autres dossiers, utilisez @source « ../app/**/*.{html,js} ».
  • Configuration JS oubliée : ne créez plus de tailwind.config.js. Tout se passe dans le CSS via @theme et @utility.
  • Classes dynamiques tronquées : bg-{couleur} ne marche pas (Tailwind ne peut pas deviner). Utilisez un mapping JS : const colors = { rouge: ‘bg-red-500’ }.
  • Mode sombre absent : oubli du @variant dark. Sans cette ligne, dark: ne fonctionne pas en stratégie class.
  • CSS de 3 Mo en dev : normal car Tailwind charge tout en mode dev. La build production fait du tree-shaking et tombe à 10-20 Ko.

Checklist de validation

  • Tailwind v4 installé via @tailwindcss/vite ou @tailwindcss/postcss
  • Une seule ligne @import « tailwindcss » dans le fichier CSS principal
  • Bloc @theme défini avec au moins 3 couleurs personnalisées
  • Au moins 2 composants construits avec classes Tailwind (carte, formulaire)
  • Mode sombre configuré et bouton de bascule fonctionnel
  • Au moins 1 utility custom créée via @utility
  • Container query utilisée sur un composant réutilisable
  • Build production exécuté et taille CSS vérifiée (idéalement moins de 25 Ko)
  • VS Code Tailwind IntelliSense installé et autocomplétion fonctionnelle
  • Test mobile sur smartphone réel ou Chrome DevTools (responsive OK)
  • Test Lighthouse : performances supérieures à 90 sur mobile
  • Documentation interne avec la palette et les utilities personnalisées

Tailwind v4 — la rupture technique de 2024

Tailwind CSS v4, publie en janvier 2025 apres deux ans de developpement, marque une rupture importante par rapport a v3. Le moteur de compilation est entierement reecrit en Rust via le projet Oxide, ce qui multiplie la vitesse de compilation par 10 environ. Le poids du bundle final est reduit de 50 pour cent sur des projets typiques. La configuration migre du fichier tailwind.config.js vers du CSS pur via la directive @theme.

Pour un projet existant en v3, la migration n est pas anodine mais reste raisonnable (quelques heures). Les changements de breaking : la directive @tailwind base est remplacee par @import 'tailwindcss', certaines classes ont des noms differents (notamment shadow-sm devient shadow-xs et shadow-lg devient shadow-md), et les variables de theme se definissent en CSS plutot qu en JS.

Les nouveautes majeures

@theme inline. La configuration du design system se fait en CSS pur dans le fichier principal. Plus besoin de tailwind.config.js — les couleurs, espacements, polices se declarent en variables CSS personnalisees. Avantage : les outils CSS standards (linters, formatters, completion VS Code) fonctionnent nativement.

Detection automatique du contenu. Plus besoin de declarer les chemins dans content du config. Le compilateur Oxide detecte automatiquement les fichiers source du projet. Moins de configuration, plus de fiabilite.

Container queries natifs. Les requetes de conteneur (CSS @container) sont disponibles via les utilities @container et @sm:, @md: etc. Un pattern qui etait penible en v3 devient evident en v4.

Cascading layers natifs. Tailwind v4 utilise les @layer du CSS natif pour son ordonnancement. Resultat : meilleure interoperabilite avec d autres styles, override plus previsible, moins de surprises sur les conflits de cascade.

Variants logiques etendues. not-*, has-*, nth-* sont desormais natifs. Selectionner un parent qui a un certain enfant, ou un element qui n est pas dans un certain etat, devient direct sans recours a du CSS custom.

Performance brute. Compilation 10x plus rapide en mode dev. Sur un projet de 200 pages, on passe de 2-3 secondes a 200-400 ms par rebuild — l experience de developpement devient quasi instantanee.

Workflow moderne en pratique

Un projet TypeScript + React + Tailwind v4 en 2026 suit typiquement ce schema. Vite ou Next.js comme bundler. Le plugin tailwindcss/postcss prend en charge la compilation. Un fichier styles/main.css contient l import principal et les variables de theme. Les composants utilisent les classes utility directement dans le JSX, en s appuyant sur clsx ou tailwind-merge pour combiner classes conditionnelles.

Pour les patterns recurrents, le pattern cva (class-variance-authority) ou les variants tailwind-variants structurent les composants reutilisables avec props typees. C est ce que font les bibliotheques de composants modernes comme shadcn/ui, base sur Tailwind et copier-coller des composants accessibles.

Pour le mode sombre, la combinaison media (prefers-color-scheme) et toggle manuel via classe sur le HTML root est devenue standard. La directive @variant dark de Tailwind v4 simplifie la declaration.

shadcn/ui — le pattern dominant

shadcn/ui (ui.shadcn.com), publie en 2023 par Shad, est devenu en 2026 la reference pour assembler des interfaces React professionnelles. Le principe est radical : pas de package npm a installer, mais une CLI qui copie-colle le code source des composants dans votre projet, ou vous pouvez le modifier librement. Vous possedez le code.

Tous les composants utilisent Tailwind v4 pour le style, Radix UI pour l accessibilite, et class-variance-authority pour les variants. Plus de 50 composants disponibles (Button, Dialog, DropdownMenu, Table, DatePicker, Form avec react-hook-form integre). Pour un projet en 2026, choisir shadcn/ui evite de reinventer ces composants et garantit l accessibilite par defaut.

Les pieges classiques v3 vers v4

shadow-sm / shadow-lg renommes. En v4, les noms ont decale. shadow-sm devient shadow-xs, shadow devient shadow-sm, etc. La codemod officielle (npx @tailwindcss/upgrade) automatise la migration sur la majorite des projets.

Couleurs avec opacite. En v3, bg-blue-500/50 fonctionnait. En v4, il faut bg-blue-500/50 mais la syntaxe avec variables CSS change. Verifier les overrides custom.

Plugins tiers. Tous les plugins Tailwind v3 ne sont pas encore compatibles v4. Verifier la compatibilite avant migration, notamment pour @tailwindcss/forms, @tailwindcss/typography (mis a jour officiellement) et plugins communautaires.

FAQ

Faut-il migrer un projet existant en v3 vers v4 ?
Pas obligatoirement. v3 reste maintenue jusqu en 2026-2027. Pour un projet en developpement actif, la migration en vaut la peine (DX et performance). Pour un projet en maintenance qui ne reçoit que des correctifs, v3 reste un choix raisonnable.

Tailwind est-il vraiment plus rapide que CSS classique ?
En 2024-2026, oui sur deux fronts. La taille du CSS final apres compilation/purge est typiquement inferieure a celle d un fichier CSS ecrit a la main (parce que les utilities ne se repetent pas, et le purge supprime ce qui n est pas utilise). La vitesse de developpement est superieure pour les developpeurs qui maitrisent les utilities — penser en composition de classes plutot qu en nommage CSS.

Quels frameworks supportent Tailwind v4 nativement ?
Next.js 15+, Astro 4+, SvelteKit 2+, Nuxt 3+, Vite (n importe quelle version) supportent v4 via la pipe postcss. Les anciens frameworks ou les setups Webpack custom peuvent demander quelques ajustements.

Tailwind est-il adapte aux gros projets a 50+ developpeurs ?
Oui, c est meme un de ses points forts. La discipline impose des conventions naturelles : pas de nommage CSS arbitraire, classes utilitaires partagees, design system centralise dans @theme. La maintenance d un design system sur Tailwind est plus simple qu en CSS classique a partir d une certaine taille d equipe.

References

Partager