Pourquoi je n'imbrique pas en SCSS

Voir la vidéo

Dans cette vidéo je vous propose de découvrir pourquoi je n'apprécie pas l'imbrication en SCSS et comment cela peut être mauvais pour l'organisation de vos feuilles de style.

Qu'est que l'imbrication

Avec le preprocesseur SASS et PostCSS il est possible de mettre les règles les unes dans les autres pour mieux s'organiser.

.header {
    .logo {
        color: #000;
    }
}

Ce qui permet de générer le CSS suivant:

.header .logo {
    color: #000;
}

De la même manière, il est aussi possible de réutiliser les règles précédentes en utilisant les symboles &.

.header {
    &__logo {
        color: #000;
    }

    .dark & {
        background: #000;
    }
}

Ce qui génèrera le CSS suivant:

.header__logo {
    color: #000;
}
.dark .header {
    color: #000;
}

Plutôt pratique lorsque l'on utilise la technique BEM par exemple.

Mais c'est trop bien !

Au premier abord cette imbrication peut sembler être une bonne idée pour organiser ses règles en fonction d'un contexte particulier. Cependant, dans la réalité, cela s'avère être une lame à double tranchant. Aussi, afin de mettre les choses en perspective, voici les raisons qui me font éviter personnellement l'imbrication dans mes projets.

Raison 1 : Règles trop spécifiques

Le premier exemple cité plus haut a comme inconvénient principale de créer des règles avec une spécificité trpp importante à cause de l'accumulation de sélecteurs.

.header .navbar .logo {
    color: #000;
}

Cette spécificité rend la cascade plus difficile lorsqu'il s'agit de changer certaines propriétés. Par exemple si on souhaite appliquer un dark mode il faudra une règle qui soit au moins aussi précise.

.dark .header .navbar .logo {
    color: #FFF;
}

On préfèrera dans cette situation utiliser un selecteur plus simple.

.header-logo {
    color: #FFF;
}

En gardant des sélecteurs de premier niveau, il est plus simple de contrôler la spécificité globale de vos règles afin de pouvoir les écraser plus simple par la suite en cas de cascade.

Raison 2 : Lisibilité difficile si trop de profondeur

Si trop utilisé, l'imbrication peut créer une profondeur trop importante qui rend la lisibilité plus difficile que nécessaire (un peu comme quand on imbrique trop de conditions dans un langage de programmation).

  // ...
  &__menu {
    .icons {
      width: 100%;
      max-width: calc(var(--col-width) + 15rem);
      margin: 0 auto;

      &__item {
        position: absolute;
        z-index: -1;
        user-select: none;

        &--youtube {
          left: 30%;
          top: 82.92px;
        }

        &--facebook {
          left: 88.15%;
          right: 8.43%;
          top: 22%;
          transform: rotate(25deg);
        }
      }
    }
  }
}

Il devient alors difficile de scanner le code CSS visuellement et de prévoir les règles qui vont être générées en sortie.

Raison 3 : Les règles sont difficiles à retrouver

Les règles générées par imbrications sont aussi plus difficile à retrouver. Même si certains éditeurs sont capables de retrouver automatiquement la définition dans le SCSS à partir des classes de votre code HTML, ce n'est pas le cas de tous les éditeurs. Vous devrez alors vous reposer sur la fonction de recherche classique mais qui ne fonctionnera pas si la règle est décomposée.

// On ne trouvera pas cette règle en cherchant ".header__menu"
.header {
    &__menu {
        display: flex;
    }    
}

Raison 4 : Les reviews sont plus difficiles

Cette imbrication pose aussi des soucis lors de la revieww de code car les outils de versioning git diff montre quelques ligne autour des lignes modifiées. Aussi, à cause de l'imbrication il est souvent nécessaire de remonter plusieurs dixaines de ligne pour trouver le sélecteur associé avec la modification.

Adapter la règle à la problématique

Malgré toutes ces raisons, il y a cependant des situations où l'imbrication peut être utilisée en évitant les problèmes énoncés plus haut.

Par exemple pour des pseudos éléments ou pour définir les états associés à une propriété.

.button {

  background: blue;
  color: #FFF;
  padding: .2rem 1rem;
  border: none;

  &:hover {
    background: #FFF;
    color: #000;
  }

  &::before {
    content:'';
    background: url(img/icon.png);
    width: 100px;
    height: 100px;
  }

  &.is-active {
    box-shadow: 0 0 4px 0 lightblue;
  }

}

Dans ce cas là j'essaie de ne jamais dépasser un niveau de profondeur tout en sachant que mes recherches se baseront sur ".button". Mais si les propriétés sont trop nombreuses alors je reviens à une syntaxe CSS classique.

Aussi, l'imbrication peut servir dans le cas des media query dans le cas d'une modification simple.

.button {

  background: blue;
  color: #FFF;
  padding: .2rem 1rem;
  border: none;
  font-size: 1rem;

  @media only screen and (min-width: 1000px) {
    padding: .5rem 2rem;
    font-size: 1.2rem;
  }

}

Cependant il faut faire attention à ne pas multiplier le nombre de media query qui vont être générées en sortie. Dans ce cas, on préfèrera l'approche plus classique avec les media query en fin de fichier.

Publié
Technologies utilisées
Auteur :
Grafikart
Partager