Cet exercice consiste à utiliser le langage sass afin de créer diverses fonctions et mixins avec en utilisant des listes et des tableaux indexés (maps).
Consignes de l’exercice
Mise en place de l’exercice
Créez un dossier racine contenant une page HTML et un fichier SCSS.
Configurez le pré-processeur Sass afin de générer un fichier CSS lisible (non-compressé). La lisibilité de ce fichier est importante si vous souhaitez pouvoir vérifier le rendu de vos manipulations.
Largeur de colonnes
SCSS : Utilisez une boucle @for
permettant de créer la série de quatre classes ci-dessous. Afin de rendre le code adaptable pour obtenir un nombre de classes différents sur le même principe, vous pouvez définir une variable pour le nombre de colonnes.
.col-1 { width: 25% ; } .col-2 { width: 50% ; } .col-3 { width: 75% ; } .col-4 { width: 100% ; }
La syntaxe d’une boucle for est la suivante. On répète l’opération avec la variable $i
qui commence avec la valeur X
jusqu’à ce que $i
ait la valeur Y
.
@for $i from X through Y { }
Pour calculer la largeur de la classe col-3
, il suffit de diviser 100% par le nombre de colonnes (4), ce qui nous donne 25% et de multiplier ce pourcentage par 3.
L’objectif est de créer 4 classes, il suffit donc d’utiliser une boucle @for
qu’il faut répéter 4 fois. La variable $i
d’itération de la boucle est alors utilisée pour nommer les classes avec #{ }
et pour calculer la largeur des colonnes.
Je vous propose ici deux solutions, avec ou sans la variable $nbcol
pour définir le nombre de colonnes à créer. Après avoir défini la variable, on l’utilise pour définir le nombre de répétition de la boucle et pour calculer la largeur de la colonne.
Cette seconde solution est un peu plus longue, mais elle deviendra plus intéressante pour la suite de l’exercice…
// Solution 1 @for $i from 1 through 4 { .col-#{$i} { width: (100% / 4) * $i; } } // Solution 2 avec une variable $nbcol: 4; @for $i from 1 through $nbcol{ .col-#{$i} { width: (100% / $nbcol) * $i; } }
SCSS : Créez un mixin correspond au code de la question précédente et testez-le. Vous passerez le nombre de colonnes comme argument du mixin.
La création et l’utilisation d’un mixin respectent la syntaxe suivante :
// Déclaration du mixin @mixin nomDuMixin( $argument ){ } // Utilisation du mixin @include nomDuMixin(x);
Il suffit de reprendre le code de la solution précédente (avec la variable) et de l’intégrer dans un mixin.
La ligne @include cols(4);
est ensuite utilisée pour exploiter le mixin et générer les 4 classes.
@mixin cols($nbcol){ @for $i from 1 through $nbcol{ .col-#{$i} { width: (100% / $nbcol) * $i; } } } // Test du mixin @include cols(4);
Liste de fruits
SCSS : Créez une liste sass intitulée $fruits
et contenant les éléments suivants : banane, cerise, ananas et pomme.
Les trois solutions proposées ci-dessous sont équivalentes compte tenu de la permissivité du langage SCSS. Je vous recommande cependant de prendre de bonnes habitudes, d’être rigoureux et d’utiliser la première proposition.
// Les trois solutions suivantes sont équivalentes $fruits: "banane", "cerise", "ananas", "pomme"; $fruits: banane, cerise, ananas, pomme; $fruits: banane cerise ananas pomme;
SCSS : Utilisez une boucle permettant de créer une série de classes CSS pour chacun des fruits sous la forme suivante :
.fruit-banane { width: 50%; } .fruit-cerise { width: 50%; } .fruit-ananas { width: 50%; } .fruit-pomme { width: 50%; }
Il faut commencer par déclarer la liste, ce qui a normalement déjà été fait précédemment dans l’exercice.
Ensuite, il faut créer une boucle pour traiter tous les éléments de la liste. La boucle @each
permet donc d’extraire une variable $fruit
de la liste $fruits
. À chaque tour de la boucle, la variable $fruit
va donc correspondre à un fruit différent.
// Définition de la liste (tableau indexé) $fruits: "banane", "cerise", "ananas", "pomme"; // Boucle sur la liste pour générer les classes // Boucle pour chaque élément $fruit présents dans la liste $fruits @each $fruit in $fruits { .fruit-#{$fruit} { width: 50%; } }
SCSS : Créez un mixin correspond au code de la question précédente. La liste des fruits doit donc être un argument du mixin.
// Création du mixin @mixin listWidth($list){ @each $element in $list { .fruit-#{$element} { width: 50%; } } } // Test du mixin $fruits: "banane", "cerise", "ananas", "pomme"; @include listWidth('fruit',$fruits);
SCSS : Si ce n’est pas déjà fait, modifiez le mixin créé précédemment afin de passer le préfixe « fruit » comme un argument du mixin.
// Création du mixin @mixin listWidth($prefix, $list){ @each $element in $list { .#{$prefix}-#{$element} { width: 50%; } } } // Test du mixin $fruits: "banane", "cerise", "ananas", "pomme"; @include listWidth('fruit',$fruits); // On peut maintenant générer d'autres classes CSS sur le même principe $animaux: "chat", "chien", "rat", "souris"; @include listWidth('animal',$animaux);
SCSS : Créez une fonction sass permettant de renvoyer la valeur de la première entrée d’un tableau et testez-la sur le tableau $fruits
.
La fonction doit renvoyer la valeur banane…
// Déclaration d'une fonction @function nomDeLaFonction( $argument ){ @return "foo"; }
Pour créer cette fonction, il suffit d’utiliser la fonction native nth()
à laquelle vous passer en premier argument la liste et en second argument la valeur 1 puisque vous voulez le premier élément.
@function firstOfList($list){ @return nth($list, 1); } $fruits: "banane", "cerise", "ananas", "pomme"; .fruit::before{ content: firstOfList($fruits); }
SCSS : Créez une fonction sass permettant de renvoyer la valeur de la dernière entrée d’un tableau et testez-la sur le tableau $fruits
.
Le principe de fonctionnement de cette fonction est le même que précédemment, mais pour déterminer l’index de la dernière valeur du tableau, on compte tout simplement le nombre d’éléments présents dans le tableau avec la fonction length()
.
@function lastOfList($list){ @return nth($list, length($list)); } $fruits: "banane", "cerise", "ananas", "pomme"; .fruit::before{ content: lastOfList($fruits); }
Liste de villes
SCSS : Créez une liste sass intitulée $villes
et contenant les villes suivantes : Lyon, Paris, Marseille, Rouen et Bourg de Péage.
SCSS : Utilisez une boucle permettant de créer une série de classes CSS pour chacune des villes sous la forme suivante. Vous remarquerez que pour chaque ville, vous avez deux syntaxes différentes par exemple : Bourg de Péage et bourg-de-peage. Vous allez certainement devoir modifier votre liste.
.ville-lyon::before { display: block; content: 'Lyon'; } .ville-paris::before { display: block; content: 'Paris'; } .ville-marseille::before { display: block; content: 'Marseille'; } .ville-rouen::before { display: block; content: 'Rouen'; } .ville-bourg-de-peage::before { display: block; content: 'Bourg de Péage'; }
Pour gérer les deux syntaxes, vous devez créer des listes imbriquées. Il s’agit donc d’une liste dont les différentes entrées sont également des listes.
$villes: (lyon,"Lyon"), (paris,"Paris"), (marseille,"Marseille"), (rouen,"Rouen"), (bourg-de-peage,"Bourg de Péage");
$villes: (lyon,"Lyon"), (paris,"Paris"), (marseille,"Marseille"), (rouen,"Rouen"), (bourg-de-peage,"Bourg de Péage"); @each $ville in $villes { .ville-#{nth($ville,1)}::before { display: block; content: "#{nth($ville,2)}" ; } }
SCSS : Créez un mixin permettant de reproduire le code précédent de manière générique.
@mixin addText($list){ @each $element in $list { .ville-#{nth($element,1)}::before { display: block; content: "#{nth($element,2)}" ; } } } // Test du mixin $villes: (lyon,"Lyon"), (paris,"Paris"), (marseille,"Marseille"), (rouen,"Rouen"), (bourg-de-peage,"Bourg de Péage"); @include addText('ville',$villes);
SCSS : Si ce n’est pas déjà fait, modifiez le mixin créé précédemment afin de placer le préfixe « ville » comme argument du mixin.
@mixin addText($prefix, $list){ @each $element in $list { .#{$prefix}-#{nth($element,1)}::before { display: block; content: "#{nth($element,2)}" ; } } } // Test du mixin $villes: (lyon,"Lyon"), (paris,"Paris"), (marseille,"Marseille"), (rouen,"Rouen"), (bourg-de-peage,"Bourg de Péage"); @include addText('ville',$villes);
SCSS : Modifiez le mixin créé à la question précédente pour lui ajouter un argument facultatif permettant d’utiliser au choix le pseudo-élément ::before
ou le pseudo-élément ::after
.
@mixin addText($prefix,$list, $position:'before'){ @each $element in $list { .#{$prefix}-#{nth($element,1)}::#{$position} { display: block; content: "#{nth($element,2)}" ; } } } // Test du mixin $villes: (lyon,"Lyon"), (paris,"Paris"), (marseille,"Marseille"), (rouen,"Rouen"), (bourg-de-peage,"Bourg de Péage"); @include addText('ville',$villes); @include addText('ville',$villes,'after');
Liste réseaux sociaux
SCSS : Créez une liste intitulée $social
et contenant :
- Une liste de réseau sociaux : facebook, flickr, linkedin, twitter, vimeo et youtube ;
- Une couleur pour chaque service : #3b5998, #0063db, #007bb6, #00aced, #aad450, #bb0000.
$social: (facebook,#3b5998), (flickr,#0063db), (linkedin,#007bb6), (twitter,#00aced), (vimeo,#aad450), (youtube,#bb0000);
SCSS : Utilisez la liste créée à la question précédente pour générer une série de classes sous la forme suivante :
.social-nom-du-service { color: couleur-associee ; background-color: couleur-associee-10-pourcent-plus-claire ; }
Voici le résultat attendu :
.social-facebook { color: #3b5998; background-color: #4c70ba; } .social-flickr { color: #0063db; background-color: #0f7bff; } // etc
Pour avoir une couleur plus claire, vous pouvez utiliser la fonction lighten()
.
$social: (facebook,#3b5998), (flickr,#0063db), (linkedin,#007bb6), (twitter,#00aced), (vimeo,#aad450), (youtube,#bb0000); @each $service in $social { .social-#{nth($service,1)} { color: #{nth($service,2)}; background-color: #{lighten(nth($service,2),10%)}; } }
SCSS : Créez un mixin permettant de reproduire le code précédent de manière générique. Le préfixe « social » et le pourcentage d’éclaircissement doivent être des arguments du mixin.
@mixin colors($prefix,$list,$percent:30%){ @each $element in $list { .#{$prefix}-#{nth($element,1)} { color: #{nth($element,2)}; background-color: #{lighten(nth($element,2),$percent)}; } } } // Test du mixin $social: (facebook,#3b5998), (flickr,#0063db), (linkedin,#007bb6), (twitter,#00aced), (vimeo,#aad450), (youtube,#bb0000); @include colors('social',$social,30%);
Modifiez le mixin créé à la question précédente afin d’ajouter une option permettant de choisir d’éclaircir ou au contraire d’assombrir la couleur secondaire. L’option doit pouvoir avoir deux valeurs : light ou dark.
@mixin colors($prefix,$list,$type:"light",$percent:30%){ @each $element in $list { .#{$prefix}-#{nth($element,1)} { color: #{nth($element,2)}; @if($type == "light") { background-color: #{lighten(nth($element,2),$percent)}; } @else { background-color: #{darken(nth($element,2),$percent)}; } } } } // Test du mixin $social: (facebook,#3b5998), (flickr,#0063db), (linkedin,#007bb6), (twitter,#00aced), (vimeo,#aad450), (youtube,#bb0000); @include colors('social',$social,'light',30%);
SCSS : Créez un tableau associatif (map) intitulée $social2
contenant les mêmes informations que $social
, puis créez une série de classes sous la même forme que précédemment.
@mixin colorsMap($prefix,$map,$type:"lighten",$percent:30%){ @each $name, $color in $map { .#{$prefix}-#{$name} { color: #{$color}; @if($type == "lighten") { background-color: #{lighten($color,$percent)}; } @else { background-color: #{darken($color,$percent)}; } } } } $social2: (facebook : #3b5998, flickr : #0063db, linkedin : #007bb6, twitter : #00aced, vimeo : #aad450, youtube : #bb0000); @include colorsMap('social',$social2,'lighten',30%);
Signes du zodiaque
SCSS : Créez une map (tableau associatif) contenant les signes du zodiac. L’index doit être le nom du signe sans accent (ex : « belier ») et la valeur est le signe avec accent et une majuscule en début de mot (ex: « Bélier »).
Liste des signes : Bélier, Taureau, Gémeaux, Cancer, Lion, Vierge, Balance, Scorpion, Sagittaire, Capricorne, Verseau, Poissons.
$zodiac: ( "belier": "Bélier", "taureau": "Taureau", "gemeaux": "Gémeaux", "cancer": "Cancer", "lion": "Lion", "vierge": "Vierge", "balance": "Balance", "scorpion": "Scorpion", "sagittaire": "Sagittaire", "capricorne": "Capricorne", "verseau": "Verseau", "poissons": "Poissons" );
SCSS : À partir de la map de la question précédente, créez une série de classes sous la forme suivante :
.zodiac-belier { background-image: url("belier.svg"); } .zodiac-belier::after { content: "Bélier"; }
$zodiac: ( "belier": "Bélier", "taureau": "Taureau", "gemeaux": "Gémeaux", "cancer": "Cancer", "lion": "Lion", "vierge": "Vierge", "balance": "Balance", "scorpion": "Scorpion", "sagittaire": "Sagittaire", "capricorne": "Capricorne", "verseau": "Verseau", "poissons": "Poissons" ); @each $signe, $label in $zodiac { .zodiac-#{$signe} { background-image: url('#{$signe}.svg'); } .zodiac-#{$signe}::after { content: '#{$label}' ; } }
SCSS : Créez une map (tableau associatif) à deux niveaux intitulé $zodiac2
contenant la liste des signes du zodiaque (sans accents) au premier niveau et les informations du signe (libellé, date début et date fin) sur un deuxième niveau.
- Bélier : 21/03 – 20/04
- Taureau : 21/04 – 21/05
- Gémeaux : 22/05 – 21/06
- Cancer : 22/06 – 22/07
- Lion : 23/07 – 22/08
- Vierge : 23/08 – 22/09
- Balance : 23/09 – 22/10
- Scorpion : 23/10 – 22/11
- Sagittaire : 23/11 – 21/12
- Capricorne : 22/12 – 20/01
- Verseau : 21/01 – 19/02
- Poissons : 20/02 – 20/03
Pour chaque signe du zodiaque, nous avons donc une map dont l’index correspond au signe sans caractère spéciaux ou accents. Cet index permet de stocker une autre map avec les index label
, debut
et fin
.
Prenez l’habitude d’avoir des index sans caractères spéciaux pour éviter les erreurs d’encodage.
$zodiac2: ( "belier": ("label" : "Bélier", "debut" : "21/03", "fin" : "20/04"), "taureau": ("label" : "Taureau", "debut" : "21/04", "fin" : "21/05"), "gemeaux": ("label" : "Gémeaux", "debut" : "22/05", "fin" : "21/06"), "cancer": ("label" : "Cancer", "debut" : "2206", "fin" : "22/07"), "lion": ("label" : "Lion", "debut" : "2307", "fin" : "22/08"), "vierge": ("label" : "Vierge", "debut" : "23/08", "fin" : "22/09"), "balance": ("label" : "Balance", "debut" : "23/09", "fin" : "22/10"), "scorpion": ("label" : "Scorpion", "debut" : "23/10", "fin" : "22/11"), "sagittaire": ("label" : "Sagittaire","debut" : "23/11", "fin" : "21/12"), "capricorne" : ("label" : "Capricorne", "debut" : "22/12", "fin" : "20/01"), "verseau": ("label" : "Verseau", "debut" : "21/01", "fin" : "19/02"), "poisson": ("label" : "Poissons", "debut" : "20/02", "fin" : "20/03") ); // Seconde présentation possible plus lisible : $zodiac2: ( "belier": ( "label": "Bélier", "debut": "21/03", "fin": "20/04" ), "taureau": ( "label": "Taureau", "debut": "21/04", "fin": "21/05" ), "gemeaux": ( "label": "Gémeaux", "debut": "22/05", "fin": "21/06" ), "cancer": ( "Cancer": "", "debut": "2206", "fin": "22/07" ), "lion": ( "label": "Lion", "debut": "2307", "fin": "22/08" ), "vierge": ( "label": "Vierge", "debut": "23/08", "fin": "22/09" ), "balance": ( "label": "Balance", "debut": "23/09", "fin": "22/10" ), "scorpion": ( "label": "Scorpion", "debut": "23/10", "fin": "22/11" ), "sagittaire": ( "label": "Sagittaire", "debut": "23/11", "fin": "21/12" ), "capricorne": ( "label": "Capricorne", "debut": "22/12", "fin": "20/01" ), "verseau": ( "label": "Verseau", "debut": "21/01", "fin": "19/02" ), "poisson": ( "label": "Poissons", "debut": "20/02", "fin": "20/03" ) );
SCSS : À partir du tableau de la question précédente, créez une série de classes sous la forme suivante :
.zodiac-belier::before { content: "Bélier"; } .zodiac-belier::after { content: "Du 21/03 au 19/04"; }
$zodiac2: ( "belier" : ("label" : "Bélier", "debut" : "21/03", "fin" : "20/04"), "taureau" : ("label" : "Taureau", "debut" : "21/04", "fin" : "21/05"), "gemeaux" : ("label" : "Gémeaux", "debut" : "22/05", "fin" : "21/06"), "cancer" : ("Cancer" : "", "debut" : "2206", "fin" : "22/07"), "lion" : ("label" : "Lion", "debut" : "2307", "fin" : "22/08"), "vierge" : ("label" : "Vierge", "debut" : "23/08", "fin" : "22/09"), "balance" : ("label" : "Balance", "debut" : "23/09", "fin" : "22/10"), "scorpion" : ("label" : "Scorpion", "debut" : "23/10", "fin" : "22/11"), "sagittaire" : ("label" : "Sagittaire","debut" : "23/11", "fin" : "21/12"), "capricorne" : ("label" : "Capricorne", "debut" : "22/12", "fin" : "20/01"), "verseau" : ("label" : "Verseau", "debut" : "21/01", "fin" : "19/02"), "poisson" : ("label" : "Poissons", "debut" : "20/02", "fin" : "20/03") ); @each $signe, $infos in $zodiac2 { .zodiac-#{$signe}::before { content: map-get($infos, "label"); } .zodiac-#{$signe}::after { content: 'Du #{map-get($infos, "debut")} au #{map-get($infos, "fin")}'; } }
Mixins divers
SCSS : Créez un mixin permettant de positionner un élément en absolu en utilisant un paramètre d’emplacement et une distance qui devra avoir une valeur par défaut.
@mixin position($position, $value:10px){ position: absolute; @if($position=="tr"){ top: $value; right: $value; } @if($position=="tl"){ top: $value; left: $value; } @if($position=="br"){ bottom: $value; right: $value; } @if($position=="bl"){ bottom: $value; left: $value; } }
Une autre possibilité consiste à distinguer les deux axes x et y.
@mixin position($x, $y, $value:10px){ position: absolute; @if($x=="l"){ left: $value; } @else { right: $value; } @if($y=="t"){ top: $value; } @else { bottom: $value; } }
SCSS : Créez un mixin permettant de créer un triangle rectangle isocèle à partir de trois paramètres : la direction (haut, bas, gauche, droite), la taille et la couleur.
@mixin triangle($size, $direction , $color){ width: 0; height: 0; border: $size solid transparent; @if($direction == 'top'){ border-top-width: 0 ; border-bottom-color: $color; } @if($direction == 'bottom'){ border-bottom-width: 0 ; border-top-color: $color ; } @if($direction == 'left'){ border-right-width: 0 ; border-left-color: $color ; } @if($direction == 'right'){ border-left-width: 0 ; border-right-color: $color ; } } // Exemples d'utilisation du mixin .triangle-top { @include triangle(150px, 'top', darken(#A51F86,10%)); } .triangle-bottom { @include triangle(100px, 'bottom', #A51F86 ); } .triangle-left { @include triangle(80px, 'left', lighten(#A51F86,10%)); } .triangle-right { @include triangle(60px, 'right', lighten(#A51F86,20%)); }
Un grand merci pour ces exercices bien détaillé en explications !!
Merci pour vos encouragements !
J’adore ces exercices ! Merci beaucoup pour votre contenu !
Ravi que cela vous plaise !