humeur

As-tu déjà entendu parler du « CSS in Js » ? Non ? voici un avant-goût. Oui ? voici quelques réflexions…

Disclaimer

Sujet toujours un peu controversé dans le milieu du Frontend, je vous livre ici un retour d’expérience que j’espère mesuré car le débat sur le sujet est parfois très passionné.

J’ai utilisé des librairies comme Emotion pour me faciliter l’implémentation puis j’ai poussé mes lectures pour tenter de comprendre les enjeux.

Cela ressemble à quoi ?

Rapidement du code avec un exemple basique :

import styled from "@emotion/styled"

const Notice = styled.p`
    color: #721c24;
    background-color: #f8d7da;
    padding: .75rem 1.25rem;
    margin-bottom: 1rem;
    border: 1px solid #f5c6cb;
    border-radius: .25rem;
`;

const Demo = () => <Notice>Ici une notice !</Notice>;

Source

Un peu de contexte

CSS ? Js ?

On a le CSS d’un côté :

CSS décrit la façon dont les éléments doivent être affichés à l’écran, sur du papier, en vocalisation, ou sur d’autres supports

on a le Js de l’autre :

JavaScript (qui est souvent abrégé en « JS ») est un langage de script léger, orienté objet, principalement connu comme le langage de script des pages web.

Jusque là tout va bien mais si on mélangeait les deux ?

C’est ce que propose le CSS-in-Js. Le CSS est généré dans le JavaScript qui le rattache au DOM en injectant dans le head de la page une balise style et des classes css uniques sur les éléments stylisés (qui ressemblent plus à des hash d’ailleurs).

Logique de composants

découper l’interface utilisateur en éléments indépendants et réutilisables, vous permettant ainsi de considérer chaque élément de manière isolée

Source

Remarque : notez qu’ici React est pris en exemple comme source mais bien entendu ça marche avec d’autres outils comme VueJS, etc.

Derrière l’idée des composants c’est le besoin de réutiliser un code bien découpé.

Les composants peuvent aussi englober d’autres composants.

Référence biblique

Pendant des années on t’a peut-être répété la Sainte parole :

tu ne mélangeras point le CSS, le JS et le HTML

Je ne sais plus trop à quel Commandement sacré cela fait référence mais pour certains c’est le Mal, le malin, El Diablo ! Ne montrez jamais à ces gens VuesJS !!!

React avait pourtant débarqué entre temps en disant grosso modo « fuck » à ce genre de considérations avec son JSX qui mélange HTML (ou presque) et js.

Et alors maintenant on voudrait tout mélanger ?

La logique globale

Une technique pragmatique pour avancer peut être de se poser la question suivante :

Quel problème cela peut-il résoudre ?

ça peut même vous indiquer si oui ou non telle technologie est pertinente ou pas pour votre projet.

Supprimer le CSS inutile

Sans la « logique composants », c’est plus délicat de supprimer des lignes de code CSS.

Pourtant, c’est statistiquement fréquent d’embarquer du CSS pour rien, c’est presque inhérent au CSS / HTML. C’est aussi relativement complexe d’identifier le code CSS qui pourra être supprimé sans affecter négativement certaines pages.

Le CSS-in-Js prétend résoudre ça !

Dynamiser des styles

On a parfois besoin de dynamiser des styles en fonction d’une vue ou d’une action de l’utilisateur.

Le CSS-in-Js prétend résoudre ça !

const Pill = styled.button`
  background-color: ${getPillColor};
`

function getPillColor(props) {
   if (props.mod !== 'truth') {
       return 'blue';
   } else {
       return 'red';
   }
}

Contrairement aux styles inline de React, on garde la même syntaxe que CSS, ainsi background-color et non backgroundColor :

const inlineStyles = {
    backgroundColor: "blue",
};

Les styles inline de React existent mais tout n’y est pas supporté et la syntaxe est contraignante à l’écrit.

Limiter la portée du code

En CSS (natif, je ne parle pas des librairies qui sont légions sur le sujet), tout est global, on a pas de notion de scope. En français on appelle ça « portée ».

L’idée est donc de trouver un moyen de limiter la portée du code CSS à ce qui nous intéresse et non de l’ouvrir à tout le site car c’est source de conflits.

Autrement dit, je code du CSS, je veux être sûr que je ne vais pas casser un truc quelque part !

Le CSS-in-Js prétend résoudre ça !

Des avantages en « cascade » ?

Du peu que je viens d’évoquer je suppose d’autres avantages :

  • performance nettement accrue pour l’utilisateur final
  • réduction du stress car la portée du code est limitée
  • facilité d’intervention pour des équipes avec des niveaux d’expérience très variables
  • pas d’apprentissage supplémentaire, ça reste du CSS

Hype ou pas hype ?

Si je me place 2 minutes à l’envers de celui qui vient de vous décrire avec un enthousiasme, qui n’est qu’apparent, sa découverte de CSS-in-Js, il vient quelques limites.

À l’ouest rien de nouveau

Rapidement, tous les avantages décrits ne sont pas propres à CSS-in-Js, bien d’autres frameworks, librairies, adressaient déjà ces problèmes quand CSS-in-Js n’étaient même pas encore une idée. C’est d’autant plus vrai que le monde JavaScript est un univers riche et foisonnant où les ressources fleurissent tous les jours.

Certaines techniques existent par exemple pour résoudre les soucis de portée : CSS modules, Shadow DOM.

Cela dit attention, le support navigateurs pour ces outils n’est pas toujours complet, c’est souvent réservé aux navigateurs les plus récents. Bien vérifier ce point !

Rien que la méthode BEM, si bien appliquée résout pas mal de soucis classiques.

Cela n’enlève pas ses qualités à CSS-in-Js mais ça n’en fait pas non plus une révolution.

L’argument maintenance

La logique de composants nous fait penser à une meilleure organisation.

Tout est au même endroit dans l’application, les styles, le js, pour chaque composant. Certes, mais, je trouve ça paradoxalement fouillis.

Si on veut appliquer un minimum de styles, on va vite atterrir avec 15-20 lignes de CSS. L' »effet wow » dans l’organisation est peu convaincant car le moindre composant titre, bouton, formulaire va vite devenir un fichier énorme.

CSS-in-Js ne résout pas ce problème. Ce n’est pas non plus horrible ni pire au final mais certainement pas idéal.

Les faux problèmes

Le temps de lancer la critique et quelqu’un a la bonne idée de remédier au problème, joies de l’open source :

La [non] coloration syntaxique dans l’éditeur était souvent mise en avant pour tourner la technique au ridicule mais c’était sans compter sur ce genre d’initiative. Après ce n’est pas compatible partout, faut ajouter une extension, on peut encore trouver à redire ^^.

La sacro sainte séparation du HTML, du js et du CSS est en revanche un faux problème à moins d’évoquer des problématiques de cache, server-side rendering, qui peuvent s’entendre dans certains cas mais donc dans un contexte et pas en général.

Le choix des librairies

Y a pas qu’Emotion sur le créneau, on peut aussi citer :

Chaque librairie amène son approche et ses fonctionnalités. Il sera par conséquent plus malin d’utiliser telle librairie plutôt qu’une autre en fonction du projet.

Quand faut-il en faire ?

Au final c’est bien la seule question qui compte. Tous les projets ne sont pas faits pour mais certains projets gagneraient peut-être à l’utiliser.

Pour le dire autrement, on cherche le meilleur ratio bénéfice/perte (de temps ^^).

On ne prendra pas trop de risque à le recommander (au moins à l’essai) pour des applis web en React.

Cela se marie très bien avec Gatsby par exemple.

Source

Conclusion

Ce petit tour d’horizon du CSS dans le Js est maintenant terminé. La technique semble être un concentré de fonctionnalités existantes avec plusieurs librairies disponibles qui offrent chacune leurs avantages.

Tant qu’à faire du CSS dans le composant, autant opter pour cette approche plutôt que de faire du CSS inline en React. C’est vraiment pénible je trouve à écrire dans le deuxième cas.

Pour autant, encore en cette fin 2019, je me demande tout de même si la techno est assez mature malgré les nombreux avantages qu’elle présente.