Tailwind a changé la façon d'écrire les styles dans les applications web, en remplaçant les classes nommées par un ensemble de petites classes utilitaires composées directement dans le balisage. La version 4 a changé la façon de travailler avec l'outil lui-même, et plus que ne le suggère le numéro de version.
Le plus grand changement est la disparition du fichier de configuration JavaScript. Les couleurs, les espacements, les polices et tout le reste se décrivent désormais directement dans une feuille de styles, sous forme de variables CSS. Un fichier JavaScript fonctionne encore si tu le pointes explicitement, mais il a cessé d'être la voie par défaut.
Le second changement concerne le moteur, réécrit de zéro en Rust. Les builds complets sont plusieurs fois plus rapides, et les rebuilds incrémentaux à l'enregistrement d'un fichier sont quasi instantanés.
La configuration dans une feuille de styles
Plutôt que d'exporter un objet de réglages, tu les décris en CSS, dans un bloc réservé au thème.
@import "tailwindcss";
@theme {
--color-brand: #0f766e;
--color-brand-light: #14b8a6;
--font-heading: "Inter Variable", sans-serif;
--spacing-section: 6rem;
}Les classes utilitaires naissent de ces valeurs, donc une couleur définie ainsi est disponible partout où une couleur est attendue.
L'avantage est plus grand qu'il n'y paraît et va au-delà du confort. Les valeurs sont de simples variables CSS : elles apparaissent dans les outils de développement, peuvent être lues depuis JavaScript, et peuvent être surchargées à un endroit précis sans reconstruire le projet.
Ça résout un problème que l'approche précédente obligeait à contourner. Un thème sombre, un thème pour un client particulier, ou une variante de couleur pour une seule section se résume à surcharger des variables dans une portée choisie, plutôt qu'à générer des jeux de classes séparés.
Au-delà du thème, trois autres éléments sont disponibles : définir tes propres classes utilitaires, définir tes propres variantes, et nommer des plugins. Tout dans le même fichier, à côté du reste de tes styles.
@utility card-shadow {
box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 8px 24px rgb(0 0 0 / 0.08);
}
@custom-variant dark (&:where(.dark, .dark *));
@plugin "@tailwindcss/typography";Une variante personnalisée est celle des trois qu'on oublie le plus souvent, et elle résout un problème concret : elle permet de décrire un état ou une portée une seule fois et de l'utiliser comme n'importe quel préfixe intégré, au lieu de répéter le même sélecteur à une douzaine d'endroits.
Le nom de la directive trompe ici et mérite d'être mémorisé précisément. Une variante se définit avec @custom-variant, alors que la directive @variant elle-même fait autre chose : elle applique une variante existante à des règles à l'intérieur d'un bloc CSS ordinaire. Le nom plus court vient des versions préliminaires de la quatrième version, donc les tutoriels écrits à cette époque donnent une syntaxe qui ne fonctionne plus aujourd'hui.
Exigences navigateurs
C'est la réserve la plus importante de cette version, et c'est à vérifier avant de démarrer une migration, pas après.
La version 4 exige des navigateurs plus récents : Safari à partir de la version 16.4, Chrome à partir de la version 111 et Firefox à partir de la version 128. Les plus anciens n'afficheront simplement pas les styles correctement.
La raison est technique et mérite d'être comprise, car elle tranche la question. L'outil s'appuie sur des mécanismes CSS qu'on ne peut pas remplacer : l'enregistrement de propriétés personnalisées et le mélange de couleurs. Ce ne sont pas des choses pour lesquelles il existe un filet de sécurité pour les anciens navigateurs, donc il n'y a pas de contournement possible ici.
La conclusion pratique est simple et inconfortable. Si ton application doit fonctionner sur des navigateurs plus anciens, la version 4 est écartée et tu restes sur la version 3. Ce n'est pas une question de confort, mais d'impossibilité technique.
Ça vaut le coup de vérifier ça dans des données de trafic réelles plutôt que dans des suppositions. Si ton projet contient une liste de navigateurs pris en charge, une seule commande répond directement à la question.
npx browserslist "> 0.5% in PL, last 2 versions, not dead"Sur une application destinée à des clients externes, en particulier dans le secteur public ou dans des pays où le renouvellement des appareils est plus lent, la part des navigateurs anciens est souvent plus élevée que l'intuition ne le suggère. Si le résultat affiche un Safari antérieur à 16 ou un Chrome antérieur à 111, la décision est prise, et ça ne vaut pas la peine de la contester à coups de contournements.
Migrer depuis la version 3
L'éditeur fournit un outil qui automatise la transition, et ça vaut le coup de commencer par lui, car il prend en charge la majeure partie du travail mécanique.
git switch -c tailwind-migration
npx @tailwindcss/upgrade
git diff --statCréer une branche séparée avant de le lancer n'est pas une prudence excessive. L'outil modifie des fichiers de template dans tout le dépôt, et relire un millier de lignes modifiées est bien plus facile quand tu peux les comparer à un point de départ et les annuler d'une seule commande.
Il remplace les dépendances, déplace la configuration du fichier JavaScript vers la feuille de styles, et corrige les noms de classes dans les templates. Il nécessite une version plus récente de l'environnement d'exécution, ce qui vaut le coup de vérifier avant de le lancer.
Quelques choses restent à faire à la main, et c'est elles qui prennent du temps.
La première, ce sont les classes renommées. Les classes séparées pour l'opacité ont disparu au profit d'une notation combinant une couleur avec une opacité. Certains noms de classes liés à flexbox ont changé aussi. L'outil corrige ça dans les templates, sans atteindre les noms construits dynamiquement dans le code.
La deuxième, ce sont les classes utilitaires personnalisées définies dans la couche réservée aux utilitaires. Dans la nouvelle version, elles arrêtent de réagir aux variantes, donc une classe fonctionne jusqu'à ce que tu essaies de l'utiliser avec un préfixe de survol. La réponse consiste à les déplacer dans la directive prévue pour ça.
La troisième, c'est l'ordre des styles. La nouvelle version utilise des couches de cascade, et les styles hors des couches ont la priorité sur ceux qui sont dedans. Ça veut dire qu'une feuille de styles incluse à côté, par exemple celle d'une bibliothèque de composants, peut commencer à surcharger des choses que Tailwind surchargeait auparavant.
Conseil pratique : migre sur une branche séparée et relis l'apparence visuellement, plutôt que de vérifier seulement que le projet se construit. Les changements dans l'ordre des styles ne signalent aucune erreur ; ils déplacent simplement des choses de quelques pixels à des endroits que personne n'avait prévus.
Installation et outils de build
La façon de le brancher a changé avec la version, et connaître la bonne voie pour ton projet vaut le coup, car les anciens tutoriels décrivent une méthode dépassée.
Avec les outils de build de nouvelle génération, un plugin dédié est disponible, nettement plus rapide qu'en passant par une couche de traitement de styles. C'est la voie recommandée pour les projets sur Vite et tout ce qui est construit dessus.
Avec Next.js et les autres frameworks utilisant une couche de traitement de styles, le branchement se fait via un paquet de plugin séparé. Une chose à noter : dans la version 4, le plugin a été extrait dans son propre paquet, donc une configuration copiée depuis un ancien tutoriel ne fonctionnera simplement pas.
Le besoin d'indiquer où se trouvent les classes a disparu aussi. La version précédente demandait de lister les chemins vers les fichiers de templates ; la version actuelle les détecte elle-même, en ignorant ce qui est exclu du contrôle de version. Ça supprime toute une catégorie de problèmes de classes qui n'étaient jamais générées parce que quelqu'un avait oublié d'ajouter un répertoire.
L'import est maintenant une seule ligne au lieu de trois directives séparées. Un détail, mais facile à manquer pendant une migration, et les anciennes directives ne sont plus reconnues.
Les couches de cascade et la coexistence avec d'autres CSS
Cette partie cause des soucis sur les projets où Tailwind n'est pas la seule source de styles.
La nouvelle version place ses styles dans des couches de cascade, ce qui ordonne les choses à l'intérieur de l'outil et introduit une conséquence à retenir. Les styles hors de toute couche ont la priorité sur ceux qui sont à l'intérieur des couches, quel que soit l'ordre du document et quelle que soit la spécificité du sélecteur.
En pratique, ça veut dire qu'une feuille de styles d'une bibliothèque de composants, incluse à côté, commence à gagner contre les classes utilitaires. Le symptôme trompe : la classe est dans le balisage, visible dans les outils de développement, et pourtant sans effet.
Il y a deux réponses. La première consiste à envelopper la feuille de styles tierce dans une couche qui t'appartient au moment de l'import, ce qui la ramène dans le même mécanisme d'ordonnancement. La seconde consiste à indiquer explicitement l'ordre des couches en haut de ta feuille de styles, pour qu'il ne dépende pas de l'ordre des imports.
Quand tu travailles avec des kits de composants prêts à l'emploi, celui décrit dans le texte sur Mantine par exemple, règle ça au début du projet. Plus tard, ça veut dire fouiller dans les styles à la recherche d'endroits où quelque chose surcharge autre chose sans raison visible.
Tailwind face aux alternatives
| Solution | Point fort | Faiblesse | Quand la choisir |
|---|---|---|---|
| Tailwind | Écriture rapide, cohérence, pas de styles morts | Balisage difficile à lire, exigences navigateurs | Un projet construit à partir de composants |
| Modules CSS | CSS ordinaire, contrôle total, aucune dépendance | Nommer les classes, plus de fichiers | Une équipe qui préfère l'approche classique |
| Styles dans le composant | Styles proches de la logique, valeurs dynamiques | Coût à l'exécution, popularité moindre | Un style fortement dynamique |
| Un kit de composants prêt à l'emploi | Apparence incluse, moins de décisions | Plus difficile de s'écarter du style imposé | Un panneau d'administration, une application interne |
La première ligne gagne sur un projet assemblé à partir de composants, car le balisage difficile à lire cesse d'avoir de l'importance : les classes sont au même endroit, dans la définition d'un composant, plutôt qu'éparpillées dans tout le projet.
Elle perd sur des pages écrites directement dans le balisage, sans couche de composants. Trente classes sur un seul élément deviennent alors un vrai problème plutôt qu'un détail esthétique.
Retiens que la première ligne accompagne souvent la dernière. Des kits comme shadcn/ui et daisyUI sont construits sur cette couche, donc choisir l'un n'exclut pas l'autre.
La pratique quotidienne
Quelques choses qui, sur la durée, séparent un projet lisible d'un enchevêtrement de classes.
Extrais les jeux de classes répétés dans des composants plutôt que dans tes propres classes raccourcies. Un composant porte avec lui une structure et un comportement, alors qu'une classe raccourcie ne porte que l'apparence, donc la première solution s'adapte mieux et ne crée pas son propre système de noms parallèle.
Quand un projet ne repose pas sur React, les kits pilotés par attributs économisent beaucoup de travail. Preline UI propose des composants Tailwind qui fonctionnent sans aucun framework, donc ça s'intègre aussi bien dans Astro, un template côté serveur, ou un simple fichier HTML. Vérifie juste la licence, car certains de ces kits séparent une édition gratuite et une édition commerciale.
Compose les classes conditionnelles avec un outil conçu pour ça, plutôt qu'en concaténant des chaînes. La concaténation manuelle conduit à deux classes contradictoires qui atterrissent sur le même élément, et c'est celle qui apparaît le plus tard dans la feuille de styles générée qui gagne.
Ne construis pas de noms de classes dynamiquement à partir de fragments. L'outil scanne le code à la recherche de noms complets, donc un nom assemblé à partir d'un préfixe et d'une variable ne sera pas détecté, et la classe ne sera pas générée. C'est la cause la plus fréquente d'un style qui fonctionne en local et disparaît après un build.
Utilise les valeurs hors de l'échelle avec parcimonie. Quelques endroits comme ça, ça va ; plusieurs dizaines signifient que l'échelle est mal choisie, et le thème mérite d'être corrigé plutôt que contourné à chaque fois.
Standardise l'ordre des classes automatiquement, avec un plugin pour ton outil de formatage. Ça supprime toute une catégorie de discussions en revue de code et fait en sorte que les diffs du dépôt montrent de vrais changements plutôt que des classes réordonnées.
Le plugin d'éditeur qui suggère les classes vaut le coup aussi. En plus de compléter les noms, il montre quel style se cache derrière une classe donnée, ce qui, en phase d'apprentissage, raccourcit le chemin vers la compréhension de l'échelle d'espacement plus que la lecture de la documentation. Sur une équipe d'expérience mixte, c'est l'une des rares choses qui accélèrent vraiment l'intégration d'une nouvelle personne.
La dernière chose concerne le mode sombre. Décide dès le départ s'il suit le réglage du système ou un choix de l'utilisateur stocké dans l'application. Changer cette décision plus tard veut dire revoir chaque endroit utilisant la variante sombre, car les deux mécanismes demandent un balisage différent.
Erreurs courantes
La première, c'est migrer vers la version 4 sans vérifier les exigences navigateurs. Les navigateurs anciens n'afficheront pas les styles, et aucun filet de sécurité n'existe.
La deuxième, ce sont les noms de classes construits dynamiquement à partir de fragments. L'outil ne les détectera pas, donc la classe n'est jamais générée, et le problème ne remonte qu'après un build.
La troisième, ce sont les classes utilitaires personnalisées laissées dans l'ancienne couche après migration. Elles arrêtent de réagir aux variantes, ce qui se traduit par une classe qui fonctionne et un état de survol qui ne fonctionne pas.
La quatrième, c'est vérifier seulement que le projet se construit après migration. Les changements dans l'ordre des styles ne signalent aucune erreur ; ils déplacent les choses visuellement.
La cinquième, c'est créer tes propres classes raccourcies au lieu de composants. Ça produit un système de noms parallèle, exactement ce dont cet outil était censé te libérer.
La sixième, c'est l'abus de valeurs hors de l'échelle. Plusieurs dizaines d'endroits comme ça signifient que le thème est mal choisi et mérite d'être corrigé.
La septième, c'est inclure la feuille de styles de quelqu'un d'autre à côté sans lui assigner de couche. Les styles hors des couches battent les classes utilitaires, et le symptôme est une classe visible dans le code source de la page qui ne fait rien, sans raison apparente.
FAQ
Qu'est-ce que la version 4 a changé ?
Avant tout, l'endroit où vit la configuration : les couleurs, les espacements et les polices se décrivent désormais dans une feuille de styles comme des variables CSS plutôt que dans un fichier JavaScript. Le moteur a été réécrit, ce qui rend les builds nettement plus rapides et les rebuilds à l'enregistrement quasi instantanés.
Est-ce que le fichier de configuration JavaScript fonctionne encore ?
Oui, à condition de le pointer explicitement depuis la feuille de styles. Il a cependant cessé d'être la voie par défaut, et les nouvelles capacités se décrivent en CSS, donc sur un nouveau projet, commence directement avec la nouvelle approche.
Puis-je migrer si j'ai des utilisateurs sur des navigateurs anciens ?
Non. La version 4 exige des versions de navigateurs plus récentes et s'appuie sur des mécanismes qu'aucun filet de sécurité ne peut remplacer. Avec une obligation de prendre en charge des appareils plus anciens, tu restes sur la version 3.
Pourquoi ma classe ne fonctionne-t-elle pas après un build ?
Le plus souvent parce que son nom est assemblé dynamiquement à partir de fragments. L'outil scanne le code à la recherche de noms complets, donc un nom construit à partir d'une variable ne sera pas détecté. La réponse consiste à écrire des noms complets dans le code et à choisir entre eux.
Tailwind convient-il aux grands projets ?
Oui, à condition de travailler avec des composants. Les classes regroupées dans des définitions de composants restent lisibles ; éparpillées directement dans le balisage, elles cessent de l'être. C'est le critère principal, plutôt que la taille du projet elle-même.
La documentation se trouve sur le site du projet, et le passage depuis la version précédente est décrit dans le guide de migration.