Dans cette vidéo je vous propose de découvrir le principe du CSSinJS.
Qu'est ce que c'est ?
Avant de commencer il est important de définir ce qu'est le CSSinJS et en quoi il difère de la manière "traditionnelle" de faire du CSS.
Comme le nom l'indique l'objectif est de générer les règles CSS depuis le JavaScript.
function Box ({ padding, children }) {
return (
<div css={{ background: 'white', padding: padding * 10 }}>{children}</div>
);
}
Au premier abord on peut se dire que cela revient à utiliser l'attribut style
de l'élément, mais la librairie de CSSinJS va plutôt générer une (ou plusieurs) règles CSS qu'elle va ensuite injecter dans l'en tête de la page.
<div class="cx13039yn">Mon texte</div>
Pourquoi ?
Maintenant on peut se demander pourquoi utiliser cette approche là, plutôt que l'approche classique qui consiste à créer les règles dans le CSS en liant à l'HTML via des sélecteurs.
Limiter la portée
Le premier objectif est de permettre de regrouper tout (style & fonction) à un seul endroit tout en évitant que le style déborde sur le reste des éléments.
En générant les noms des classes automatiquement le CSSinJS va permettre de limiter la portée des règles et permet aussi de se poser moins de questions sur les conventions de nommages.
<!-- Il n'est pas nécessaire de faire du JS, exemple avec VueJS -->
<template>
<div class="box">Bonjour le monde</div>
</template>
<style scoped>
.box {
background: white;
padding: 10px;
}
</style>
Chargement à la demande
Maintenant que le style est lié à l'élément il est plus simple de morceler le chargement du style et de faire en sorte que si un élément ne soit pas chargé son style ne soit pas chargé non plus. Cela permet de ne pas charger une grosse feuille de style qui contient peut être des sélecteurs pour des éléments qui ne sont pas présents sur la page (au prix souvent d'un coût supplémentaire à l'éxécution)
Une composition plus prévisible
Un autre problème résolu par le CSSinJS est la composition. Lorsqu'un élément a plusieurs classes, les styles ne sont pas appliqués en fonction de l'ordre des classes mais en fonction de l'ordre des déclaration (et de la spécificité des sélecteurs).
<style>
.bg-blue {
background: blue;
}
.btn {
background: red;
color: #fff;
}
</style>
<button class="btn bg-blue">Je suis rouge !</button>
Dans ces conditions il peut être difficile d'anticiper (et d'organiser) le style de certains éléments. En travaillant avec des objets ce problème est éliminé car l'ordre des paramètres va primer sur le reste.
const styles = {
bgBlue: { background: 'blue' },
btn: { color: '#fff', background: 'red' }
}
<button class={css({...styles.btn, ...style.bgBlue})}>Je suis bleu !</button>
Génération en JavaScript
Enfin un dernier avantage est la possibilité de profiter de l'écosystème JavaScript pour générer nos styles.
const styles = {
background: opacify(COLORS.white, 10)
position: 'absolute',
...inset(0)
}
Un nouvelle approche avec de nouveaux problème
Même si tout ce que l'on a dit précédemment semble intéréssant il est important de voir aussi les compromis à faire en adoptant cette nouvelle approche afin de choisir le bon outil en fonction de la situation.
Un coût à l'éxécution
La génération des classes et l'injection du style a un coût qui viendra s'ajouter lors du rendu de chacun de vos composant. Cela demandera aussi plus de travail au niveau du navigateur qui verra les règles de styles appliquées à la page évoluée tout au long de la vie de votre application (les navigateurs sont devenus très bon pour optimiser le chargement d'une feuille de style CSS classique).
Pas de standard
L'approche CSSinJS est implémentée par plusieurs librairies qui proposent toutes des approches et des fonctions différentes (et il en existe déjà beaucoup !). On aura alors un socle de développement qui sera moins stable et plus évolutif que le standard CSS avec ces sélecteurs.
En plus de cela, beaucoup de ces outils vont dépendre d'une librairie ou d'un framework particulier. Par exemple on ne fera pas du CSSinJS de la même manière suivant que l'on travaille avec VueJS, Svelte ou React.
Rendu côté serveur
Le problème du rendu côté serveur se pose aussi dans de nombreuses implémentations du CSSinJS. Certaines de ces librairies extraient le style dans une balise <style>
placée en début de page. Même si cela permet de ne charger que le style critique à l'application cela ne permet pas par exemple la mise en cache par le navigateur comme ça peut être le cas avec un fichier CSS séparé. Dans certains cas (comme avec VueJS ou Svelte) on peut exporter le CSS séparément mais se retrouvera alors dans une situation où le CSS extrait peut varier d'une page à l'autre.