Il n’y a que les imbéciles qui ne changent pas d’avis et c’est mon avis depuis toujours
Coluche
J’ai toujours regardé avec dédain les tentatives des dev JS pour contourner l’écriture de CSS mais je commence à considérer que les outils de CSS-in-JS type Emotion sont la bonne solution pour les webapp React.
J’ai été intégrateur, à faire de la belle CSS séparée du code HTML. On finit quand même vite par construire des monstres ou se prendre les pieds dans le tapis dès qu’on fait plus de quelques pages types.
Pour résoudre le problème, éliminons le. C’est ce que proposent les conventions comme BEM. Si je caricature, il s’agit principalement de retirer les sélecteurs CSS un attribuant une ou plusieurs classes spécifiques à chaque contexte. C’est franchement moche mais ça fonctionne.
CSS-Modules va un peu plus loin. Le principe est le même mais on permet au développeur d’utiliser un nommage plus agréable. C’est l’outil de génération qui gère la complexité au lieu du développeur.
J’avoue que j’aime bien CSS-modules. C’était mon favori jusqu’à présent.
Ça revient à juste gérer un fichier par composant en se limitant à des sélecteurs très simples pour ne pas créer de conflits de spécificité. On reste sur du CSS standard et sur une approche proche de mes habitudes historiques. Mieux : L’intégration peut se faire indépendamment du langage de développement de l’applicatif.
C’est top mais ça se base sur des composants qui ne bougent pas beaucoup, dont on connait à l’avance tous les états.
Dès qu’il s’agit de cumuler plusieurs états, le résultat dépend de l’ordre d’écriture dans la CSS. Parfois c’est bien prévu, parfois non.
Dès qu’il s’agit de rendre des choses très dynamiques, il faut de toutes façons sortir des CSS modules. Vous voulez que dans la vue large les items de navigation se colorent au survol en fonction de la catégorie destination déterminée dynamiquement mais qu’ils utilisent la couleur neutre dans la vue réduite destinée aux mobiles ? Vous êtes à poil et il va falloir composer avec d’autres façons d’injecter des CSS, peut-être même tâtonner sur les priorités entre classes.
Les classes utilitaires et CSS atomiques à la Tachyon sont là pour industrialiser en poussant encore plus loin.
J’ai une classe par valeur à appliquer : .ms7-ns applique la septième valeur du catalogue (7) comme taille horizontale maximum (ms pour max-width) si la fenêtre a une taille supérieure au point de rupture « small » (ns pour non-small).
Ça n’offre quasiment aucune abstraction utile (uniformiser les valeurs on a déjà plein d’outils plus efficaces). C’est vite cryptique, lourd, et monstrueux dès qu’on multiplie les valeurs et les points de rupture possibles.
Le seul intérêt par rapport à écrire directement les attributs style c’est que ça permet d’accéder aux media query et aux pseudo-sélecteurs.
Malheureusement non seulement ça ne résout pas les conflits de priorités mais ça les empire. Si je spécialise un composant existant en y ajoutant une classe liée à une directive déjà présente, je joue à la roulette russe. Il faut absolument que mon composant initial prévoit lui-même tous les cas possibles pour savoir quelle classe injecter et ou ne pas injecter. Pas d’alternative.
J’ai vraiment l’impression d’un retour en arrière monstrueux avec ces CSS atomiques, cumuler les défauts sans aucun avantage, et c’est probablement ce qui m’a fait rejeter par principe les CSS-in-JS jusqu’alors.
Les CSS-in-JS c’est finalement pousser la logique de Tachyons un cran plus loin. Quitte à décider de tout dans le code HTML, autant écrire directement les styles à cet endroit là en utilisant la vraie syntaxe CSS et en y ajoutant la possibilité d’accéder aux media query et aux pseudo-sélecteurs.
Emotion c’est ça. On est à la croisée entre le « j’écris tout dans un attribut style » et le « j’attache un module CSS ».
En fonctionnement basique c’est comme un CSS module sans le sélecteur. Je donne les directives en CSS on ne peut plus classiques et j’ai accès aux media query, aux pseudo-sélecteurs et aux animations avec une syntaxe proche de ce que font les préprocesseurs habituels (et en phase avec la direction que prend la syntaxe CSS elle-même).
const style = css`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
&:hover {
color: blue;
}
`
Je peux directement ajouter le résultat aux classes CSS de mon composant. Il se chargera de générer un nom de classe, de créer la CSS correspondante dans le document, et de lier les deux, comme avec CSS-Modules.
L’exemple est peu parlant. On a juste l’impression d’un CSS-Modules écrit dans le fichier JS.
L’avantage c’est que je ne suis pas limité aux valeurs en dur. Je peux avoir des valeurs dynamiques venant de mon Javascript ou de mon thème, et je n’en limite pas les effets à ce que me permettent les variables CSS.
Je peux aussi réutiliser, composer ou surcharger un élément ou un bloc de styles avec un autre sans risque de conflit de priorité.
Tachyons me donnait l’impression de cumuler les inconvénients, ici j’ai vraiment l’impression de cumuler les avantages.
La seule contrainte c’est que mon code CSS se retrouve dans mes fichiers JS. C’est moche quand c’est dit ainsi mais pour une app en React, on a de toutes façons un fichier par composant HTML et ça a du sens de grouper HTML, JS et CSS lié au composant ensemble quand ils sont fortement liés. C’est d’ailleurs le choix de VueJS.
Ce n’est forcément pas adapté à tout, et si vous voulez rester génériques les CSS-Modules sont à mon avis l’option la plus saine, mais pour un code React je crois que c’est là que je commencerai par défaut désormais.
Laisser un commentaire