La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Sass mixin ou placeholder

par Kitty Giraudel, 8 août 2018, css, sass, article original paru le 30 janvier 2014 dans Sitepoint

Kitty Giraudel est un spécialiste internationalement reconnu de Sass. Il explique ici clairement et simplement la différence entre mixin et placeholder, comment utiliser l'un ou l'autre ou... combiner les deux.


Quand j’ai commencé à m’amuser avec Sass il y a un an et demi, j’ai mis un peu de temps à comprendre la différence entre inclure un mixin et étendre un placeholder. En fait, la notion même de placeholder relevait un peu de la magie noire pour moi.

Si vous êtes dans le même cas, pas d’inquiétude. Aujourd’hui nous allons apprendre exactement à quoi sert un mixin, et quand utiliser un placeholder. Vous verrez qu’ils ont chacun leur utilité et ne doivent pas être confondus.

Remarque : Je parle ici de Sass, mais ce que je décris pourrait s’appliquer à d’autres préprocesseurs CSS, tels Stylus ou LESS, vous pouvez donc adapter le contenu de cet article à l’outil de votre choix.

Pour commencer, un petit rappel sur les mixins et les placeholders.

Un petit mix

Un mixin est une directive qui vous permet de définir des règles multiples dépendant de plusieurs arguments. Un peu comme une fonction qui au lieu de retourner une valeur renverrait du contenu CSS. Voici la définition donnée par Sass Reference :

Les mixins vous permettent de définir des styles qui peuvent être réutilisés dans votre feuille de style sans avoir besoin de recourir à des classes non-sémantiques telles que .float-left. Les mixins peuvent aussi contenir des règles CSS et tout ce qui est permis dans un document Sass. Ils peuvent prendre des arguments qui vous permettent de produire de nombreux styles avec très peu de mixins.

Voilà pour la terminologie. Supposons maintenant que vous ayez repéré quelques déclarations répétées plusieurs fois dans votre feuille de style. Vous connaissez le principe DRY (Don’t Repeat Yourself) et vous décidez de corriger cela en écrivant un mixin :

@mixin center() {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.container {
  @include center();
  /* Other styles here... */
}

/* Other styles... */

.image-cover {
  @include center;
}

NB : si vous ne passez pas d’argument dans votre mixin, vous pouvez omettre les parenthèses. Vous pouvez même les omettre dans la définition du mixin.

Avec ce mixin, vous n’avez pas besoin de répéter ces trois lignes à chaque fois que vous voulez centrer un élément, il suffit d’inclure le mixin. Pratique, non ?

Parfois vous aurez besoin de construire des "raccourcis" pour quelques propriétés. Par exemple, width et height. N’êtes-vous pas fatigué d’écrire toujours ces mêmes lignes, surtout quand elles ont la même valeur ? Réglons ça avec un mixin !

@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}

Simple, n’est-ce pas ? Remarquez que j’ai rendu le paramètre $height optionnel en lui donnant la même valeur par défaut que $width, directement dans la définition du mixin. Maintenant, à chaque fois que vous voudrez définir les dimensions d’un élément, vous pourrez écrire simplement :

.icon {
  @include size(32px);
}

.cover {
  @include size(100%, 10em);
}

NB: pour un autre exemple de syntaxe "sucrée", vous pouvez consulter celle que j’ai réalisée pour éviter d’avoir à écrire top, right, bottom, left et position à chaque fois que je veux un positionnement différent de static.

Placeholders

Les placeholders sont un peu bizarres. Ce sont des classes qui ne sont pas rendues commes telles lorsque votre SCSS est compilé. Et alors ? me direz-vous. En fait, tout irait bien s’il n’y avait cette directive @extend. Mais commençons par le commencement, voici comment on écrit un placeholder :

%center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

En gros, c’est exactement comme écrire une classe, sauf qu’elle est préfixée avec % au lieu d’un point. Le placeholder suit les mêmes règles de nommage que les classes.

Si maintenant vous compilez votre SCSS, vous ne verrez pas ce code dans le fichier généré en CSS. Pour l’instant, ce placeholder est totalement inutile. Pour qu’il serve à quelque chose, il faut utiliser @extend :

.container {
  @extend %center;
}

Sass va aller chercher le contenu du placeholder %center pour l’appliquer à .container.

Autre application extrêmement utile d’@extend, vous pouvez étendre des sélecteurs CSS existants, de la façon suivante :

.table-zebra {
  @extend .table;

  tr:nth-of-type(even) {
    background: rgba(0, 0, 0, 0.5);
  }
}

C’est un cas d’usage très courant. Dans l’exemple ci-dessus, nous demandons à la classe .table-zebra de se comporter exactement comme la classe .table (en étendant les règles relatives à cette dernière), puis nous ajoutons des règles spécifiques à zebra.

L’extension de sélecteurs est très pratique quand vous développez votre site/application avec des composants modulaires. Pour en savoir plus sur le sujet, vous pouvez consulter l’article Sass : tout sur @extend.

Lequel utiliser ?

Eh bien, comme toujours dans notre domaine, ça dépend. Cela dépend du contexte et de votre objectif.

Le meilleur conseil serait : si vous avez besoin de variables, utilisez un mixin. Sinon, étendez un placeholder. Il y a deux raisons à cela :

  • D’abord, on ne peut pas passer de variables dans un placeholder, donc vous ne pourrez pas générer un CSS spécifique au contexte, comme vous le pourriez avec un mixin.
  • Ensuite, la façon dont Sass gère les mixins les rend assez peu pratiques lorsqu’ils ne sont pas utilisés avec des variables contextuelles. Pour le dire simplement : Sass recopie le rendu de votre mixin à chaque fois que vous l’utilisez, ce qui a pour résultat un code dupliqué (contraire au principe DRY) et des feuilles de styles alourdies.

Si nous reprenons notre tout premier exemple :

@mixin center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.container {
  @include center;
}

.image-cover {
  @include center;
}

Le résultat CSS après compilation sera :

.container {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.image-cover {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Vous remarquez la duplication de CSS. Ce n’est pas bien grave s’il n’y a que 3 lignes de code, mais vous imaginez ce que ça peut donner avec des mixins plus complexes et utilisés plus souvent dans un projet. Essayons de réécrire notre petit exemple en utilisant maintenant un placeholder :

%center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.container {
  @extend %center;
}

.image-cover {
  @extend %center;
}

Voici le résultat CSS après compilation :

.container,
.image-cover {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Beaucoup mieux ! La compilation s’effectue par groupage de sélecteurs, sans répétition de styles. Conclusion : lorsque vous voulez éviter d’écrire les mêmes propriétés, si vous savez qu’elles ne varieront pas, il faut utiliser un placeholder.

Par contre, si vous voulez écrire les mêmes propriétés mais avec des valeurs différentes, le mixin est préférable. Et si vous avez un groupe de valeurs fixes et variables, vous pouvez essayer une combinaison des deux.

%center {
  margin-left: auto;
  margin-right: auto;
  display: block;
}

@mixin skin($color, $size) {
  @extend %center;
  background: $color;
  height: $size;
}

a {
  @include skin(pink, 10em);
}
b {
  @include skin(blue, 90px);
}

Dans cet exemple, le mixin étend le placeholder pour les valeurs fixes, ce qui génère un CSS propre :

a,
b {
  margin-left: auto;
  margin-right: auto;
  display: block;
}

a {
  background: pink;
  height: 10em;
}

b {
  background: blue;
  height: 90px;
}

Et voilà !

    Articles de Kitty Giraudel traduits dans La Cascade

    Voir la page de Kitty Giraudel et la liste de ses articles dans La Cascade.
    Article original paru le 30 janvier 2014 dans Sitepoint
    Traduit avec l'aimable autorisation de Sitepoint et de Kitty Giraudel.
    Copyright Sitepoint © 2014