Chapitre 6 : Fonctions, maps et boucles
1 min de lecture
Chapitre 6 : Fonctions, maps et boucles
Objectif
À la fin de ce chapitre, vous savez écrire une fonction qui renvoie une valeur, ranger des couleurs dans une map, et produire quelques classes avec une boucle. Le vert du succès quitte le code en dur. Les boutons restent sur le mixin action.
Le dossier mon-sass continue. La veille se lance depuis la racine :
npx sass --watch scss/style.scss css/style.css
_variables.scss, _carte.scss et _boutons.scss sont en place. index.html charge css/style.css. .succes et .erreur étendent %encart. La bordure verte est encore écrite #2a6f4e dans style.scss.
Une fonction renvoie une valeur
Un mixin écrit des déclarations. Une fonction renvoie une seule valeur, à placer là où une couleur ou une mesure est attendue. Elle ne crée pas de règle.
Créez scss/_outils.scss. Le souligné empêche Sass d’en faire une feuille à part, comme pour les autres partiels. Les @use restent en tête : plus bas, le compilateur répond @use rules must be written before any other rules.
@use "variables";
@use "sass:map";
$messages: (
"succes": #2a6f4e,
"erreur": variables.$accent,
);
@function message($nom) {
$couleur: map.get($messages, $nom);
@if $couleur == null {
@error "Couleur de message inconnue : #{$nom}.";
}
@return $couleur;
}
@function espace($parts) {
@if $parts < 1 {
@error "espace attend un nombre d’au moins 1, reçu #{$parts}.";
}
@return variables.$espace-s * $parts;
}
@use "sass:map" charge les fonctions de map livrées avec Dart Sass. Sans cette ligne, map.get s’arrête sur There is no module with namespace "map". map.get lit une entrée. @function nomme le calcul, @return donne le résultat. Sans @return, la compilation s’arrête : Function finished without @return.
espace(2) multiplie variables.$espace-s par 2. Cette variable vaut 0.5rem, le produit vaut 1rem. espace(3) vaut 1.5rem. Le nombre 0 est refusé avant le calcul. Le terminal affiche alors espace attend un nombre d’au moins 1, reçu 0.
Une fonction n’écrit pas de CSS. Un sélecteur dans son corps donne @function rules may not contain style rules. Une déclaration seule, color: red;, donne @function rules may not contain declarations. Le bloc des boutons reste dans le mixin action.
Ce fichier ne sort rien tant que personne n’appelle les fonctions. La map non plus : ce n’est pas une règle.
Nommer le vert du succès
Dans style.scss, chargez le partiel avec les autres. Chaque fichier qui a besoin d’un module l’écrit lui-même. _outils.scss a déjà son @use "variables". style.scss garde le sien.
@use "variables";
@use "carte";
@use "boutons";
@use "outils";
Remplacez les deux couleurs de bordure. Le reste de l’encart ne change pas.
.succes {
@extend %encart;
border-color: outils.message("succes");
}
.erreur {
@extend %encart;
border-color: outils.message("erreur");
}
Enregistrez. L’écran ne bouge pas : vert #2a6f4e, bordeaux #9b2226. Dans css/style.css, la map a disparu, le nom message aussi. Il reste la valeur choisie :
.succes {
border-color: #2a6f4e;
}
.erreur {
border-color: #9b2226;
}
variables.$accent valait déjà #9b2226. La fonction a choisi cette entrée et l’a posée sur border-color. Le partage du padding et du rayon vient encore de @extend, pas de la map.
Essayez outils.message("alerte"). La clé n’existe pas, map.get renvoie null, et @error arrête la veille. Le terminal affiche Couleur de message inconnue : alerte. et marque la ligne de style.scss. Remettez "succes". La clé est une chaîne entre guillemets : "succes" et succes ne sont pas la même entrée.
Trois marges avec @each
Une map peut aussi décrire des mesures. Sous les messages, dans style.scss, nommez trois paliers déjà présents dans _variables.scss.
$paliers: (
"s": variables.$espace-s,
"m": variables.$espace-m,
"l": variables.$espace-l,
);
@each $nom, $valeur in $paliers {
.marge-#{$nom} {
margin-bottom: $valeur;
}
}
@each parcourt la map. À chaque tour, $nom reçoit la clé et $valeur la mesure. #{$nom} colle cette clé dans le sélecteur. Sans les accolades, .marge-$nom s’arrête sur expected selector.
Le CSS livré contient trois règles :
.marge-s {
margin-bottom: 0.5rem;
}
.marge-m {
margin-bottom: 1rem;
}
.marge-l {
margin-bottom: 2rem;
}
Ajoutez trois paragraphes dans index.html, sous les messages.
<p class="marge-s">Marge courte.</p>
<p class="marge-m">Marge moyenne.</p>
<p class="marge-l">Marge large.</p>
Rechargez. L’écart sous chaque ligne suit 0.5rem, 1rem, puis 2rem. La boucle a écrit ces règles parce qu’elle est dans style.scss, le fichier compilé. Placée dans _outils.scss, elle sortirait aussi, dès le @use "outils", même sans ces paragraphes. On la laisse à côté du HTML qui s’en sert. Une fonction, elle, attend un appel.
Compter avec @for
@each suit une liste que vous avez nommée. @for compte. Ajoutez ceci sous les marges.
@for $i from 1 through 3 {
.espace-#{$i} {
margin-top: outils.espace($i);
}
}
through inclut la borne 3. Trois classes sortent : .espace-1 avec 0.5rem, .espace-2 avec 1rem, .espace-3 avec 1.5rem. Le produit est celui de espace(). Remplacez through par to : la boucle s’arrête avant 3, .espace-3 disparaît, les deux autres restent. Remettez through. La différence tient dans ce seul mot.
Ce que la boucle ne doit pas faire
Trois classes utiles, d’accord. Une boucle qui invente douze variantes dont le HTML n’a pas besoin les écrit quand même dans css/style.css. Le fichier gonfle, la page ne change pas. On compte les sélecteurs livrés, pas le nombre de lignes dans la source.
Les boutons ne passent pas dans @each. Leurs fonds diffèrent, et action reçoit déjà $fond et $encre-bouton. Une boucle qui recopierait le mixin répéterait display et le survol. Le mixin garde les boutons. La fonction garde les calculs. La boucle ne sert que lorsque plusieurs sélecteurs partagent la même forme et que la page les utilise.
Exercice
Reprenez mon-sass. index.html reste lié à css/style.css. La veille tourne.
- Créez
scss/_outils.scssavec la map$messages,message()etespace(). Dansstyle.scss, ajoutez@use "outils";et remplacez les deuxborder-color. - Rechargez. Les bordures ne changent pas. Dans
css/style.css,#2a6f4eet#9b2226sont là. Les mots$messagesetmessagesont absents. - Appelez
outils.message("alerte"). LisezCouleur de message inconnue : alerte.Remettez"succes". - Ajoutez
$palierset la boucle@each. Ajoutez les trois paragraphes. Vérifiez.marge-s,.marge-met.marge-l, avec0.5rem,1remet2rem. - Ajoutez la boucle
@foravecthrough. Trois classes, de.espace-1à.espace-3. Remplacez parto:.espace-3disparaît. Remettezthrough. - Collez
.bouton { background: red; }dansmessage(), au-dessus de@return. Lisez@function rules may not contain style rules.Effacez cet essai.
C’est réussi quand les deux messages passent par message(), quand les trois marges sont dans le CSS, et quand l’essai dans la fonction a disparu. Si la bordure verte devient bordeaux, la clé lue est "erreur", ou #2a6f4e a été remplacé dans la map.
À retenir
- Une fonction renvoie une valeur avec
@return. Elle ne contient ni règle ni déclaration. @use "sass:map"puismap.getlisent une map. Une clé absente vautnull:@errordoit l’arrêter.- La map et la fonction disparaissent du CSS. Seule la valeur renvoyée reste.
@eachparcourt une map.#{$nom}construit le sélecteur. Sans interpolation, le compilateur ditexpected selector.@for ... throughinclut la dernière valeur.tos’arrête juste avant.- Une boucle écrit chaque classe dans le fichier livré. Les boutons restent sur le mixin : leurs valeurs changent.
La suite
Les calculs ont un nom, les couleurs de message aussi, et trois marges sortent d’une seule boucle. Le dossier tient encore sur une poignée de fichiers à plat. La leçon suivante, « Organiser un vrai projet », range ces partiels par rôle. Vous garderez mon-sass, _outils.scss, le mixin action, l’encart %encart et les classes déjà compilées.