CSS

Comment Tailwind CSS m'est devenu indispensable.

Je n'étais pourtant pas du tout emballé au départ.

Lancé fin 2017, Tailwind s'est très rapidement fait une solide réputation dans l'univers des frameworks CSS. Désormais très populaire (plus de 63 000 étoiles sur Github) et utilisé sur une multitude de sites, ce package reste controversé et est souvent accusé de réinventer la roue.

Pour me faire ma propre idée, je l'ai testé sur un projet Next.js (disponible ici). Pour quel bilan ?

A quoi ça sert ?

Tailwind, c'est un concept simple. Le framework apporte un lot de classes utilitaires permettant de styliser sans écrire de CSS directement. Du CSS inline camouflé derrière d'autres noms.

Prenons un exemple d'un bloc HTML des plus basiques, stylisé en CSS.

<div class="main-content">
    <h1>Titre</h1>
    <p>Contenu</p>
</div>

<style>
    .main-content {
        display: flex;
        padding: 1rem;
    }

    .main-content > h1 {
        font-size: 1.5rem;
        color: red;
    }

    .main-content > p {
        color: blue;
        padding-top: 0.5rem;
    }
</style>

Avec Tailwind, voici le code à écrire pour reproduire à l'identique l'exemple.

<div class="p-4 flex">
    <h1 class="text-2xl text-red-600">
        Titre
    </h1>
    <p class="pt-2 text-blue-600">
        Contenu
    </p>
</div>

En regardant ce code, on peut se demander si ce n'est pas un retour en arrière. Un retour à une époque où écrire du CSS inline était courant avant de devenir une honte, une mauvaise pratique. La séparation des préoccupations (separation of concerns) est ici complètement bafouée.

Et ce n'est pas le pire à encaisser. L'exemple ci-dessus est simpliste et court mais dans un cas réel, il n'est pas rare d'associer un nombre conséquent de propriétés CSS à un bloc de code. On se retrouve alors avec une ligne interminable remplie de classes utilitaires.

<div class="p-6 max-w-md flex items-center justify-center rounded-xl bg-white cursor-pointer shadow-lg hover:p-10 hover:bg-black">
    ...
</div>

Pour ma part, c'est le moment où j'ai failli lâcher l'affaire. Et je ne suis visiblement pas le seul dans ce cas vu ce qui est écrit en introduction de la documentation de Tailwind.

"Now I know what you’re thinking, “this is an atrocity, what a horrible mess!” and you’re right, it’s kind of ugly. In fact it’s just about impossible to think this is a good idea the first time you see it — you have to actually try it."

Qu'on peut traduire brièvement par "Vous pensez que c'est horrible, et c'est vrai, c'est assez moche. Mais même s'il est impossible de penser que c'est une bonne idée au premier abord, vous devez l'essayer.".

Ce que j'ai fini par faire, pour mon plus grand bonheur.

De sérieux avantages

Un élément qui revient souvent concernant les qualités de Tailwind est sa capacité à produire un fichier CSS le plus petit possible. Le framework se charge de générer un fichier ne contenant que les classes utilitaires présentes au sein du code du projet, ce qui évite les surcharges inutiles qu'on pouvait fréquemment voir avec l'importation complète de Bootstrap par exemple.

Je trouve cependant que ses qualités majeures se trouvent ailleurs, à l'usage.

Des composants sinon rien

Dupliquer du code n'est jamais agréable à faire et complique la maintenance sur la durée. Mais il fréquent de voir des blocs entiers de code copiés pour diverses raisons (manque de temps, fatigue, mauvaises pratiques, ...).

Le fait d'utiliser Tailwind décourage très fortement cette pratique et dirige naturellement vers la création de composants dédiés.

Il est relativement facile d'envisager de copier ceci

<span class="mon-mot-en-gros">Bidule</span>

si le css associé est dans un fichier séparé.

.mon-mot-en-gros {
    font-size: 3rem;
    font-weight: bold;
    color: red;
    text-decoration: underline;
    line-height: 2rem;
    text-transform: uppercase;
}

.mon-mot-en-gros:hover {
    font-size: 6rem;
    color: blue;
}

Il sera plus difficile de se sentir à l'aise si le code à copier est plus conséquent.

<span class="text-5xl hover:text-8xl font-bold text-red-600 hover:text-blue-600 underline leading-8 uppercase">
    Bidule
</span>

Le découpage en composants devient d'autant plus primordial ici, ce qui est bien souvent une excellente pratique. Une contrainte de Tailwind devient un avantage à l'usage.

Fin de la guerre des fichiers CSS

En repartant de l'exemple précédent, on peut se demander s'il est bien grave de dupliquer un si petit bout de code si son CSS est rangé dans son propre fichier. Mais après avoir travaillé sur des dizaines de projets aux multiples fichiers CSS (ou SASS), j'ai constaté que l'organisation du CSS représente quasiment toujours un souci à terme.

Plusieurs écoles s'affrontent. L'école du gros fichier CSS unique, celle qui propose un fichier par composant, celle qui intègre le CSS dans le JS. J'en oublie certainement d'autres.

Pour avoir déjà testé les deux premières, je ne les trouve pas satisfaisantes.

  • Le fichier unique est ingérable pour des projets conséquents.
  • Le fichier par composant est déjà mieux sur le papier. Mais il est dur d'éviter les conflits avec des fichiers CSS plus globaux.

Tailwind s'affranchit de ces débats. Plus besoin de chercher la ligne CSS coupable du visuel désastreux de notre bouton, il suffit d'ouvrir le fichier du composant associé et lire les classes utilitaires.

Donner des noms c'est long

Probablement le point qui m'apporte le plus de confort. Je ne me rendais pas compte du temps perdu à chercher des noms pour les classes CSS. C'est pourtant un point connu dans le domaine informatique, avec la fameuse citation de Phil Karlton :

"There are only two hard things in Computer Science: cache invalidation and naming things."

Chercher des noms, éviter les conflits, garder une cohérence, avoir des noms les plus limpides possibles. Tout ceci est bien plus chronophage que l'on ne pourrait le penser.

Supprimer totalement cette contrainte grâce à Tailwind s'est révélé être un bol d'air frais pour l'esprit. Je peux me concentrer sur la conception de mon composant, sur son usage, plutôt que sur le fait de trouver un nom pour les éléments qu'il comprend.

Quelques contraintes

Rien n'est jamais parfait, Tailwind ne fait pas exception. Si son usage ne fait pas l'unanimité, c'est qu'il comprend son lot de défauts.

Le CSS est standard et fiable

Le plus gros point noir à mes yeux. Tailwind reste un package à installer et demande une compilation pour générer au final ... du CSS.

Un projet directement stylisé grâce à du CSS sera compris par un navigateur web, sans efforts supplémentaires. Le code reste valide sur une longue période.

A contrario, si Tailwind disparaît de la toile, les projets l'utilisant deviennent soudainement obsolètes. Cependant ce scénario reste peu probable et la conséquence n'est pas insurmontable. Il faudrait alors réécrire des classes CSS pour remplacer les classes utilitaires de Tailwind. Ce serait pénible mais le risque paraît faible et la conséquence peu coûteuse.

Un apprentissage supplémentaire

Utiliser Tailwind, cela revient à manipuler des dizaines de classes utilitaires. Comme pour Bootstrap, on se retrouve à devoir apprendre une grande quantité de noms si l'on veut les utiliser rapidement sans naviguer en permanence dans la documentation.

De plus, on apprend à utiliser un outil spécifique et ces connaissances ne seront pas applicables ailleurs, contrairement à l'apprentissage du CSS.

Heureusement cette contrainte est adoucie grâce aux noms des classes utilitaires, qui sont assez instinctifs. On peut aussi avoir une autocomplétion au sein de VSCode.

Pour ma part je garde toujours un onglet ouvert sur la documentation officielle mais je n'y jette un oeil que rarement désormais. Après un seul projet réalisé avec Tailwind.

Des lignes interminables

Vous vous souvenez de l'exemple du début ?

<div class="p-6 max-w-md flex items-center justify-center rounded-xl bg-white cursor-pointer shadow-lg hover:p-10 hover:bg-black">
    ...
</div>

Pour ma part, je n'apprécie pas du tout les lignes à rallonge et j'aime voir tout le code à l'écran. Sans avoir à scroller sur la droite.

Les premières longues lignes de classes utilitaires se sont révélées assez douloureuses à écrire. Je voyais ce défaut comme un point bloquant, ce qui m'a amené à chercher des solutions.

La documentation officielle propose d'organiser les classes automatiquement (dans l'ordre conseillé par le framework) grâce à Prettier. Un bon début pour éviter le chaos mais pas une réponse à mon problème.

J'ai alors découvert clsx. Un tout petit package (228B) qui facilite l'écriture des classes CSS dans un projet React. A la fois bien pratique pour écrire des classes de façon conditionnelle, cet utilitaire me permet de ranger mes classes Tailwind d'une façon qui me convient bien mieux.

Avec clsx, l'exemple devient le code suivant :

<div
    className={clsx(
        'p-6 hover:p-10',
        'max-w-md',
        'flex items-center justify-center',
        'rounded-xl',
        'bg-white hover:bg-black',
        'cursor-pointer',
        'shadow-lg'
    )}
>
    ...
</div>

Au premier abord, ce n'est pas très séduisant. Beaucoup de lignes de code pour une simple balise. Pourtant, je suis très satisfait de cette solution.

Le nombre de lignes est un petit défaut mais vient lui aussi encourager la découpe du code en composants. En séparant les fonctionnalités en petits éléments, ces lignes supplémentaires ne représentent pas une contrainte.

Je trouve aussi plus facile de voir en un coup d'oeil les choix visuels effectués sur ce bloc de code. Pas besoin d'ouvrir un fichier CSS pour se renseigner ni de scroller. Si je veux rajouter une condition (hover, media query), je peux le faire rapidement sur la ligne d'une classe utilitaire.

Tailwind : c'est oui ou c'est non ?

Mon bilan ne contiendra pas de surprise : Tailwind c'est un grand oui !

Ses avantages me libèrent considérablement l'esprit et ses contraintes sont facilement contournées. Elles deviennent même positives lorsqu'elles encouragent la création de composants plus petits, plus facilement modifiables et testables. Ce qui peut aussi encourager l'utilisation de Storybook.

Son succès me semble amplement mérité. Si j'ai pu finaliser le projet Juju & Caillou (un super site de recettes de cuisine) c'est en partie grâce à Tailwind. J'ai pu itérer plus rapidement, garder davantage de motivation sur la durée, tout en ayant un code plus facile à faire évoluer.

Ses créateurs n'ont pas menti : il faut le tester avant de juger.

Suivez au mieux mes découvertes

Pas besoin de vérifier ce site régulièrement, je me charge de vous partager les nouveaux articles dès leur publication.

Aucun spam, possibilité de se désinscrire en un clic. Juste une façon simple et rapide de lire mon contenu.

Dernière mise à jour : 10/12/2022