En tant que développeur frontend avec près de 15 ans d'expérience, j'ai été témoin de l'évolution du développement Web. Pour moi, cela a parcouru un long chemin depuis l'époque du téléchargement de fichiers modifiés via FTP (oui, GitHub a été lancé il y a 15 ans, mais je ne l'ai découvert qu'en 2011) à l'ère moderne des interfaces réactives, des bibliothèques d'interface utilisateur et des sites Web directement générés à partir de Figma.
Pourtant, je rencontre toujours des projets qui utilisent des styles imbriqués comme :
.some-class ul li div a { /* some style */ }
ou,
#nav .nav-link svg { /* some style */ }
Cela peut sembler choquant, mais de telles pratiques de codage imprègnent tout, des projets de plusieurs millions de dollars à croissance rapide aux humbles startups.
Voyons pourquoi cette approche peut poser des problèmes.
Les styles profondément imbriqués entraînent souvent des conflits de style, surtout si vous avez un gros projet. CSS, en tant que feuille de style en cascade, descend en cascade et s'applique aux éléments en fonction de leur spécificité. Les styles profondément imbriqués peuvent involontairement remplacer d'autres styles en raison de leur spécificité.
Considérez cet exemple :
.some-class ul li div a { color: red; } ... .some-class a { color: blue; }
Vous pouvez vous attendre à ce que tous les liens dans .some-class
soient bleus. Cependant, en raison de la plus grande spécificité de la première règle, tout lien imbriqué dans un ul > li > div
sera rouge et non bleu. Cela peut entraîner des incohérences visuelles inattendues et beaucoup de temps perdu à déboguer.
Comprendre le concept de spécificité (ou le « poids » des styles) en CSS est essentiel pour comprendre pourquoi l'imbrication profonde peut être gênante. La spécificité détermine quelle règle CSS s'applique si plusieurs règles sont en concurrence pour un seul élément. Il est calculé en fonction du type et de la quantité de sélecteurs.
La spécificité est calculée sur la base d'un système de pondération à quatre catégories :
Ici, considérons la règle:
body #content .data img:hover { /* some style */ }
La spécificité est 0 1 2 2 . C'est un ID ( #content ), deux classes ( .data et :hover ) et deux éléments ( body et img ).
Maintenant, considérons la règle :
#nav .nav-link svg { /* some style */ }
La spécificité ici est 0 1 1 1 . C'est un ID ( #nav
), une classe ( .nav-link
) et un élément ( svg
).
La spécificité ne fonctionne pas sur un système de "report" comme les nombres décimaux traditionnels. Par exemple, un sélecteur avec une spécificité de 0 1 0 11 n'est pas égal à une spécificité de 0 1 1 1 même si dans un système décimal, 11 et 1+1 seraient équivalents.
Enfin, le sélecteur universel ( *
), les combinateurs ( +
, >
, ~
, ' ') et la pseudo-classe de négation ( :not()
) n'ont aucun effet sur la spécificité. À l'intérieur de l'argument :not()
, cependant, les sélecteurs sont comptés comme d'habitude.
Pour les apprenants visuels, je recommande cette vidéo sur la spécificité CSS.
Comprendre la spécificité CSS et la façon dont elle est calculée vous permet d'écrire un CSS meilleur et plus prévisible et de déboguer les problèmes lorsque les styles ne sont pas appliqués comme prévu.
!important
et la spécificité Parfois, les développeurs ont recours à la règle !important
lorsqu'ils rencontrent des difficultés avec des conflits de spécificité CSS. Cette règle rend une propriété CSS extrêmement spécifique, ce qui signifie qu'elle remplacera presque toute autre déclaration.
Par exemple:
#nav .nav-link svg { color: blue; } .nav-link svg { color: red !important; }
Bien que la première règle ait une spécificité plus élevée en raison du sélecteur d'ID, la couleur du svg
serait rouge à cause du !important
dans la deuxième règle.
Bien que !important
puisse être une solution rapide aux problèmes de spécificité, il n'est pas recommandé de l'utiliser de manière intensive. Une utilisation excessive peut affecter la maintenabilité, la prévisibilité et les performances. Dans les grands projets, la surutilisation de !important
indique souvent une difficulté à gérer la spécificité CSS. Plutôt que de recourir à !important
, il est souvent préférable d'investir du temps dans la refactorisation de votre CSS et de réduire l'utilisation de sélecteurs trop spécifiques.
Vous pouvez vérifier votre produit dès maintenant 🙂. J'ai vérifié le mien :
Bien que !important
puisse être une solution rapide tentante ; c'est comme utiliser un marteau pour casser une noix. Une approche plus maintenable consiste à garder vos sélecteurs aussi simples et aussi plats que possible, ce qui rend votre CSS plus facile à comprendre, à gérer et à étendre à l'avenir. Et rappelez-vous, la meilleure façon de gagner une guerre !important
n'est pas d'en commencer une en premier lieu.
Un autre problème avec les styles profondément imbriqués est l'impact des performances sur le rendu du navigateur. Lorsqu'un navigateur applique des styles à un élément, il parcourt le DOM de droite à gauche, en commençant par le sélecteur de clé (dans nos exemples, a
et svg
) et en se déplaçant à travers les ancêtres jusqu'à ce qu'il trouve une correspondance ou atteigne le sommet. Plus le style est imbriqué, plus cette traversée prend de temps, ce qui peut affecter les performances et ralentir les temps de chargement des pages dans les projets à grande échelle.
Lorsque vous spécifiez une règle CSS, comme :
.some-class ul li a { /* some style */ }
Vous pouvez visualiser cette règle en partant du bas de l'arborescence (à partir de la balise a
) et en remontant dans l'arborescence (via li
, ul
et .some-class
).
Le navigateur cherchera d'abord tous (je veux dire TOUS) a
éléments a, puis il vérifiera si ces a
a sont à l'intérieur des éléments li
. Après cela, il vérifiera si ces éléments li
sont à l'intérieur ul
Et enfin, il vérifiera si ces ul
sont à l'intérieur d'un élément avec la classe de .some-class
.
C'est ainsi que les navigateurs lisent les sélecteurs CSS et la raison pour laquelle les sélecteurs complexes peuvent ralentir le rendu des pages. Le navigateur doit effectuer plusieurs vérifications pour chaque élément pour voir s'il correspond à la règle spécifiée. Plus la règle est profonde, plus le navigateur doit effectuer de vérifications, ce qui peut avoir un impact sur les performances.
Les modules CSS vous permettent d'écrire du CSS dans des modules individuels, qui sont limités localement au composant sur lequel vous travaillez. Cela signifie que les styles d'un module CSS ne s'appliquent qu'à ce module spécifique et ne fuiront pas ou n'affecteront pas les autres éléments de la page.
Explorons comment les modules CSS utilisent des noms de classe hachés pour assurer l'encapsulation du style. Lorsque vous utilisez des modules CSS, les noms de classe que vous définissez dans votre fichier CSS seront hachés au moment de la compilation. Ce hachage crée un nom de classe unique qui correspond à votre composant. Prenons un exemple :
Supposons que vous ayez un module CSS défini comme tel :
/* Button.module.css */ .button { color: white; background-color: blue; }
Et vous l'utilisez dans votre composant comme ceci (je préfère importer l'objet styles en tant que s
au lieu de styles
- une astuce rapide qui permet de gagner du temps de frappe et d'améliorer l'efficacité du codage) :
import React from 'react'; import s from './Button.module.css'; const Button = () => { return ( <button className={s.button}>Click me</button> ); }; export default Button;
Lorsque votre application est compilée, votre code HTML rendu peut ressembler à ceci :
<button class="Button_button__3FQ9Z">Click me</button>
Dans ce cas, Button_button__3FQ9Z
est le nom de classe haché qui a été généré à partir de votre module CSS. Notez que la structure et la longueur exactes du hachage peuvent varier en fonction de la configuration de votre projet.
Ce nom de classe unique garantit que les styles que vous avez définis dans Button.module.css
s'appliquent uniquement à ce bouton et n'affectent aucun autre élément de votre application. Cela garantit également qu'aucun autre style ne peut affecter ce bouton à moins qu'il ne cible explicitement le nom de la classe hachée. Cette encapsulation des styles est l'un des principaux avantages des modules CSS.
Une autre façon populaire de gérer CSS consiste à utiliser des bibliothèques CSS-in-JS, telles que styled-components ou emotion . Ces bibliothèques vous permettent d'écrire votre CSS directement dans votre JavaScript, ce qui présente plusieurs avantages :
Voici un exemple de la façon dont vous pouvez utiliser des composants de style dans une application React :
import React from 'react'; import styled from 'styled-components'; const Button = styled.button` color: white; background-color: ${(props) => props.primary ? 'blue' : 'gray'}; `; const App = () => { return ( <div> <Button primary>Primary Button</Button> <Button>Secondary Button</Button> </div> ); }; export default App;
Dans cet exemple, le composant Button
a des styles dynamiques qui changent en fonction de son accessoire primary
.
Si vous ne travaillez pas avec un framework JavaScript prenant en charge les modules CSS ou similaires, vous pouvez toujours gérer efficacement votre CSS en utilisant des méthodologies de dénomination telles que BEM (Block, Element, Modifier).
BEM signifie "Block Element Modifier", et c'est une méthodologie qui vous aide à créer des composants réutilisables et à partager du code dans CSS. Voici comment vous pouvez structurer votre CSS à l'aide de BEM :
/* Block */ .top-menu { } /* Element */ .top-menu__item { } /* Modifier */ .top-menu__item_active { }
Dans BEM, le « Bloc » est l'entité autonome qui a du sens en soi, l'« Élément » est une partie du Bloc qui n'a pas de sens autonome et est sémantiquement lié à son Bloc, et le « Modificateur » est un indicateur sur un bloc ou un élément utilisé pour modifier l'apparence ou le comportement.
L'utilisation d'une méthodologie cohérente telle que BEM peut faciliter la compréhension et la maintenance de votre CSS, en particulier pour les grands projets.
Il existe plusieurs façons de gérer CSS dans des projets plus importants, des modules CSS et des bibliothèques CSS-in-JS aux méthodologies de dénomination comme BEM. La clé est de trouver une approche qui correspond bien à votre équipe et à votre projet et de l'appliquer de manière cohérente. N'oubliez pas qu'écrire du CSS consiste autant à écrire du code efficace et performant qu'à écrire du code compréhensible et maintenable.
Bon codage !