Aller au contenu principal
Site en cours de refonte — quelques pages peuvent bouger ou évoluer.
23 avril 2026

Tailwind v4 : le moment où tu réalises que ta config n’est plus dans un fichier JS (et que ta migration va mordre)

Tailwind v4 est une bonne version… mais pas une mise à jour “npm install et go”. Voilà ce qui casse vraiment en migration, et une méthode simple pour reprendre le contrôle.

10 min de lecture
62 vues
réactions
Partager :
Tailwind v4 : le moment où tu réalises que ta config n’est plus dans un fichier JS (et que ta migration va mordre)

Tailwind v4, c’est le genre d’upgrade qui a l’air “techniquement propre” sur le papier… et qui te met une claque dès que tu as un projet existant. Le déclic arrive vite : ta config n’est plus juste un tailwind.config.js que tu tweaks en douce. Tu passes sur une approche CSS-first, ton tooling bouge, et certains détails (coucou les gradients et @apply) ne pardonnent pas.

Je te propose une migration sans drama. Pas un tuto “hello world”, mais un vrai parcours d’upgrade pour une app qui a déjà des composants, des overrides, des plugins et un design system à moitié “tailwindisé”.

Tailwind v4 : ce qui change vraiment (spoiler, c’est la config)

Le changement le plus important de Tailwind v4, ce n’est pas une nouvelle classe. C’est le déplacement du centre de gravité. En v3, ton cerveau vit dans tailwind.config.js : thème, content/purge, plugins, variants, extensions… En v4, tu peux (et souvent tu dois) penser config dans le CSS, via des directives dédiées.

Concrètement, ça force une question saine mais chiante : où vit ta vérité ? Dans un design token file ? Dans une config JS ? Dans un CSS global ? Si tu ne tranches pas proprement, tu finis avec des valeurs dupliquées et des classes qui “marchent” en dev mais pas en build prod.

Mon conseil : accepte que la migration, ce n’est pas “mettre à jour Tailwind”. C’est reposer l’architecture de tes styles. Si tu fais semblant, tu vas patcher au hasard pendant deux jours, puis revenir en arrière.

Migrer sans casser l’UI : ma stratégie quand je n’ai pas le droit de jouer au poker

Le piège classique, c’est de migrer et de “tester au feeling”. Tu cliques deux pages, tu te dis que ça a l’air bon, tu merges… et tu découvres la casse sur un écran que personne n’a ouvert depuis 3 mois. Tailwind, c’est du CSS généré. Donc la validation doit être visuelle, rapide, reproductible.

Ce que je fais sur une app qui compte : je me crée une page de référence qui rassemble les composants qui font mal. Les boutons, les champs, les badges, les alerts, les cards, les tableaux, les modales, les gradients, les états hover/focus/disabled, et au moins un layout “réaliste” (sidebar + header + contenu). Pas besoin que ce soit beau. Il faut que ce soit impitoyable.

Ensuite je veux un diff visuel. Peu importe l’outil : Playwright en screenshots, Chromatic si tu as Storybook, même un script maison tant que c’est automatique. L’objectif est simple : ne pas débattre. On compare avant/après et on sait où ça a bougé.

Dernier point, non négociable : un rollback facile. Une branche dédiée, un commit par étape (tooling, directives CSS, tokens, plugins), et pas de refacto “au passage”. Si tu mélanges migration Tailwind + nettoyage UI, tu ne sauras jamais ce qui a cassé quoi.

Passer en CSS-first proprement : ce que je mets dans le fichier global

En v4, tu as intérêt à traiter ton fichier CSS global comme une entrée de configuration. C’est là que tu vas déclarer tes sources (les fichiers à scanner), ton thème, et les imports Tailwind. Ça a un côté “retour aux fondamentaux” que j’aime bien, mais ça demande de la discipline : ton CSS global devient un fichier critique.

Un exemple minimaliste de ce que ça peut donner (à adapter à ton bundler et à ton arbo) :

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

/* Indique à Tailwind où chercher tes classes (équivalent du content/purge) */
@source "./src/**/*.{html,js,ts,jsx,tsx,vue,svelte}";

/* Thème / tokens : le cœur de ta migration */
@theme {
  --color-brand: #4f46e5;
  --radius-card: 12px;
}

/* Tes styles “maison” par-dessus Tailwind */
@layer components {
  .btn {
    border-radius: var(--radius-card);
  }
}

Ce point est important : ne te contente pas de “traduire” ta config JS en directives CSS. Profite-en pour stabiliser tes tokens. Si tu as déjà des couleurs “brand” en dur dans 15 endroits, v4 est un bon prétexte pour arrêter l’hémorragie.

Le piège silencieux : content/purge devient un problème de build, pas un détail

Sur Tailwind, quand la config “content” est fausse, tu as deux scénarios. Soit ton CSS devient gigantesque et tout le monde se plaint du bundle. Soit (le pire) la moitié de tes classes ne sont plus générées et tu te retrouves avec une UI “presque” correcte, mais pleine de trous.

En v4, avec l’approche CSS-first, c’est facile de se planter de chemin, surtout si tu as un monorepo, un dossier apps/, ou un framework qui planque des templates ailleurs. Ma règle : je valide ce point en tout premier, et je le valide en prod. Le dev server peut te donner un faux sentiment de sécurité.

Si tu as des classes générées dynamiquement (ex. bg-${color}-500), la migration v4 n’est pas le moment d’espérer un miracle. Tu dois assumer une stratégie explicite : soit tu élimines la génération dynamique, soit tu “safelist” correctement, soit tu passes par des mappings. Sinon tu vas passer ta semaine à courir après des classes manquantes.

Gradients : le genre de détail qui te flingue un header sans que personne ne comprenne

Les gradients font partie des trucs qui cassent “bêtement” : un renommage de classe, un changement d’API utilitaire, et tu ne t’en rends compte que sur un écran marketing ou un hero. En migration, je les traite comme un cas à part, parce qu’ils sont souvent utilisés dans des composants très visibles et rarement couverts par des tests.

Si tu viens de v3, tu as probablement des bg-gradient-to-* un peu partout. En v4, selon ton codebase et tes habitudes, tu peux te retrouver à devoir passer sur des utilitaires de gradients plus explicites (par exemple des variantes du style bg-linear-to-r). Le résultat visuel peut rester proche, mais le diff te force à toucher plein de templates.

Le bon réflexe ici, c’est d’arrêter de “corriger à la main au fil de l’eau”. Fais une passe dédiée : recherche globale des classes de gradient, mets-les toutes dans la page de référence, puis corrige avec un diff visuel sous les yeux. Sinon tu vas en oublier, garanti.

@apply en v4 : là où les migrations deviennent pénibles (et comment éviter l’enlisement)

@apply, c’est pratique… jusqu’au jour où ça te donne une fausse impression de stabilité. Beaucoup de projets ont construit des pseudo-composants CSS avec @apply, parfois dans tous les sens, parfois avec des variants, parfois en mélangeant des layers sans trop y penser. Et quand tu changes de version majeure, c’est exactement le genre de zone grise qui explose.

Ce qui arrive souvent en v4, c’est que des @apply qui passaient deviennent plus stricts, ou se mettent à échouer selon l’ordre des layers, le moment où Tailwind voit la classe, ou le fait que tu appliques des utilitaires qui n’existent plus sous le même nom. Et le pire : tu peux obtenir des erreurs qui sentent le “tooling”, alors que la vraie cause est un composant CSS trop malin.

Mon arbitrage en prod est assez tranché : je limite @apply aux composants stables (boutons, champs, badges) et j’évite d’en faire un mini-framework dans mon CSS. Si j’ai un gros paquet d’@apply fragiles, je préfère parfois revenir à des classes Tailwind dans le markup pour les zones volatiles, et garder @apply uniquement là où ça apporte une vraie valeur.

Plugins, PostCSS, Lightning CSS : la migration cachée, c’est ton tooling

Quand tu passes Tailwind v4, tu ne changes pas juste une lib CSS. Tu touches au pipeline : comment le CSS est transformé, minifié, préfixé, et comment Tailwind s’insère dans ton bundler. Tailwind v4 s’appuie davantage sur un moteur moderne (Lightning CSS), et ça a une conséquence directe : certains setups PostCSS “historiques” deviennent inutiles, d’autres deviennent incompatibles, et quelques plugins maison peuvent se comporter différemment.

Le scénario typique : tu as un postcss.config qui traîne depuis 2021, avec des plugins que plus personne n’ose toucher. En v4, tu peux te retrouver avec des doubles transformations, des ordres qui changent, ou des subtilités (autoprefixer, nesting, minification) qui ne se font plus là où tu crois.

Le conseil terrain : fais une migration en deux temps. D’abord, tu fais tourner Tailwind v4 en gardant le pipeline aussi proche que possible, juste pour obtenir une UI identique. Ensuite seulement, tu simplifies. Si tu fais “upgrade Tailwind + refonte tooling” en une fois, tu ne sauras pas si ton bug vient d’une directive v4, d’un plugin PostCSS, ou d’une minification qui a changé.

Build prod vs dev : le moment où tu découvres que “ça marche chez moi” ne veut rien dire

Sur Tailwind, le dev et le build prod ne racontent pas la même histoire. En dev, tu peux avoir du JIT, du hot reload, des comportements plus permissifs, et un scan des fichiers qui “tombe juste” parce que ton serveur voit tout. En prod, tu as l’optimisation, l’élimination de classes, la minification, et parfois des chemins de fichiers différents (CI, Docker, monorepo).

Donc pendant la migration, je me force à faire ce truc basique et pourtant souvent oublié : je build en prod tôt. Et je check une page de référence sur le build prod, pas uniquement sur le dev server. Si tu découvres au dernier moment que ton @source ne matche pas en CI, tu as perdu une journée.

Profiter de Tailwind v4 sans réécrire tout ton design system

La tentation, quand on migre, c’est de se dire : « bon, on en profite pour tout “clean” ». Mauvaise idée si ton objectif est de livrer. Tailwind v4 n’exige pas que tu réinventes tes composants. Il exige que tu clarifies où sont tes tokens, comment tu génères tes classes, et comment tu gères les exceptions.

Le meilleur compromis que j’ai trouvé : je migre d’abord en mode “compat”, j’obtiens un rendu quasi identique, puis je fais une passe d’amélioration ciblée. Par exemple, tu peux sortir tes valeurs récurrentes dans @theme, réduire les overrides CSS, et normaliser 2-3 composants clés. Mais tu ne fais pas un grand soir. Ça, tu le fais après, quand la v4 tourne et que tout le monde a arrêté de paniquer.

Si tu as un design system partagé (plusieurs apps, plusieurs repos), traite la migration comme une montée de version de lib interne. Versionne, publie, adopte progressivement. La migration “big bang” est tentante, mais elle te coûte cher dès que tu as des équipes ou des cycles de release différents.

Conclusion : Tailwind v4 est une bonne version, mais elle ne pardonne pas l’à-peu-près

Tailwind v4 simplifie pas mal de choses et pousse vers une config plus proche du terrain, dans le CSS. Mais sur un projet existant, ça te force à affronter tes dettes : tokens dispersés, @apply trop ambitieux, tooling fossilisé, content/purge approximatif.

La bonne nouvelle, c’est que tu peux migrer sans te faire mordre si tu te donnes une méthode : une page de référence, un diff visuel, un build prod tôt, et une séparation claire entre “faire marcher” et “améliorer”. Une fois que c’est en place, v4 devient un vrai terrain solide pour la suite, au lieu d’un énième patchwork de styles.

Sources

Cet article vous a plu ?

Commentaires

Laisser un commentaire

Entre 10 et 2000 caractères

Les commentaires sont modérés avant publication.

Aucun commentaire pour le moment.

Soyez le premier à donner votre avis !