Pour commencer en douceur, on va s’intéresser dans ce chapitre à l’imbrication de règles, une fonctionnalité fondamentale de Sass. Comme vous aller le voir, elle s’inscrit vraiment dans le principe « Don’t Repeat Yourself ».
- L'imbrication, pourquoi faire ?
- La référence au parent
- Imbrication de media-queries
- Bonne pratique : « The Inception Rule »
L'imbrication, pourquoi faire ?
Commençons par observer cet extrait de notre feuille de style :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | blockquote { font-style: italic; } blockquote:before, blockquote:after { content: '"'; } .quote { text-align: right; margin: 1rem 0; } .quote blockquote { font-size: 3rem; line-height: 1em; } .quote figcaption { font-family: "Grand Hotel", serif; font-size : 1.2rem; margin-top: 1rem; } .quote figcaption:before { content: '\2012 '; } |
On remarque que blockquote
, .quote
et figcaption
sont répétés plusieurs fois. Ce n’est pas encore trop rébarbatif à cette échelle là, mais ça l’est au niveau de la feuille de style en entier : on n’a pas forcément envie de répéter plusieurs fois les mêmes sélecteurs. Avec Sass, les règles concernant .quote
peuvent être écrites de la manière suivante en utilisant l’imbrication de règles :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | .quote { text-align: right; margin: 1rem 0; blockquote { font-size: 3rem; line-height: 1em; } figcaption { font-family: "Grand Hotel", serif; font-size : 1.2rem; margin-top: 1rem; } figcaption:before { content: '\2012 '; } } |
Avec l’imbrication, nous n’avons écrit .quote
qu’une seule fois et nous avons mis les blocs blockquote
, figcaption
et figcaption:before
à l’intérieur du bloc .quote
. Sass comprend lors de la compilation que les règles ne doivent concerner que les éléments <blockquote>
et <figcaption>
situées à l’intérieur d’une élément de classe .quote
. On obtient bien la même chose qu’avec le code précédent. Cependant, vous remarquez que l’on a regroupé toutes les règles concernant un module (la citation) dans un même bloc. Ainsi, le code est plus lisible, car il est mieux organisé.
On peut aussi imbriquer des propriétés CSS. Cela peut être utile pour regrouper les propriétés d’une même catégorie à l’intérieur d’un bloc. Par exemple, nous pouvons mettre dans un même bloc les propriétés font-size
et font-family
, comme ceci :
1 2 3 4 5 6 7 | figcaption { font: { family: "Grand Hotel", serif; size: 1.2rem; } margin-top: 1rem; } |
faites bien attention au deux-points (:
) après font
Voilà pour le principe de base de l’imbrication. Passons maintenant à quelques cas particuliers.
La référence au parent
On n’a pas encore réussi à imbriquer le sélecteur figcaption:before
. Vous pensez que le code suivant marchera ?
1 2 3 4 5 6 7 8 9 10 | figcaption{ font: { family: "Grand Hotel", serif; size: 1.2rem; } margin-top: 1rem; :before{ content: '\2012 '; } } |
En réalité, on obtiendra le sélecteur figcaption :before
(avec une espace) qui ne veut rien dire. Pour corriger cela, on va utiliser le sélecteur &
, qui fait référence au parent. Ainsi, ce code fonctionnera :
1 2 3 4 5 6 7 8 9 10 | figcaption{ font: { family: "Grand Hotel", serif; size: 1.2rem; } margin-top: 1rem; &:before{ content: '\2012 '; } } |
Que s’est-il passé ? Avec le sélecteur &
(l’esperluette), on a indiqué à Sass où il devait insérer le sélecteur du bloc parent. Dans notre cas, comme il n’y a pas d’espace entre &
et :before
, il n’y en aura pas après compilation entre figcaption
et le pseudo-élément.
On peut faire de même avec blockquote
:
1 2 3 4 5 6 | blockquote{ font-style: italic; &:before, &:after{ content: '"'; } } |
Il est aussi possible de s’en servir avec une pseudo-classe (&:hover
sélectionne l’élément parent au survol) ou même à la fin d’un sélecteur (section &
sélectionne l’élément parent lorsqu’il est contenu dans une balise <section>
). Toujours moins de répétitions, et toujours plus d’imbrications qui rendent le code plus lisible.
Imbrication de media-queries
Depuis quelque temps et la démocratisation du Responsive Web Design (RWD pour les intimes), les media-queries ont le vent en poupe. Justement, saviez-vous que Sass permet d’imbriquer la directive @media
? Interessons-nous à cet extrait de notre exemple :
1 2 3 4 5 6 7 8 | #description{ max-width:22rem; } @media all and (min-width: 740px){ #description{ max-width:48%; } } |
Il est possible d’imbriquer le bloc @media
à l’intérieur du bloc #description
. L’intérêt est encore un gain de clarté, puisque l’on regroupe toutes les règles concernant un module (#description
) dans un même bloc :
1 2 3 4 5 6 | #description{ max-width:22rem; @media all and (min-width: 740px){ max-width:48%; } } |
Voilà, pas grand chose d’autre à dire là-dessus, même si on reparlera un peu des media-queries dans le prochain chapitre.
Bonne pratique : « The Inception Rule »
L’imbrication est un outil puissant, mais cela ne veut pas dire qu’il faut en abuser, au risque de provoquer une pagaille inimaginable. Vous pourriez être tentés de reproduire dans la feuille de style la structure de la page HTML, un peu comme ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | html{ ... body{ ... header{ #hgroup{ ... h1{...} h2{...} } #search{ ... input{...} button{ ... &::after{...} } } } #presentation{...} } } |
Sauf que… c’est mal ! Essayez d’imaginer quels sélecteurs seront présents après la compilation :
1 2 3 | html body header #hgroup #search button::after{ ... } |
Beurk. Une telle méthode pose deux problèmes. Le premier, c’est que l’on perd en partie le principe de la cascade : les sélecteurs sont trop spécifiques, et une modification, même peu importante, du HTML risque d’imposer une modification de la feuille de style. On a donc perdu en maintenabilité. Le second, c’est que, tout bêtement, le fichier .css
sera inutilement lourd, ce qui est embêtant pour le serveur comme pour les visiteurs.
C’est là qu’intervient ce que l’on appelle « The Inception Rule ». La règle est la suivante : n’imbriquez pas plus de quatre niveaux différents. C’est une règle arbitraire et contraignante, mais je vous invite à la suivre. Si vous dépassez quatre niveaux, c’est que probablement l’un d’entre eux n’est pas nécessaire. Essayez donc de ne pas trop allonger vos sélecteurs. Il y a souvent moyen de faire plus court.
En résumé
- On peut éviter d’écrire plusieurs fois les mêmes sélecteurs, grâce à l’imbrication.
- Lors de l’imbrication, pour faire référence au bloc parent, on utilise le sélecteur
&
. - On peut imbriquer la directive
@media
pour mieux organiser son code. - Il ne vaut mieux pas dépasser quatre niveaux d’imbrication, c’est The Inception Rule.
Pour s’entraîner
Je vous invite à trouver tous les endroits où il est possible d’utiliser l’imbrication dans notre exemple, plu particulièrement en ce qui concerne l’élément #search
, qui regroupe vraiment tout ce que nous venons de voir (esperluette et media-queries compris). La correction est ici.
Dans le prochain chapitre, nous ferons un sort aux variables, de petites bestioles bien pratiques, héritées des langages de programmation.