Licence CC BY-SA

Les fonctions

Dans le chapitre sur les variables, j’ai évoqué très rapidement les fonctions. Il est temps de revenir plus en détail sur ces petites moulinettes bien pratiques. Dans ce chapitre, nous nous concentrerons sur l’utilisation des fonctions proposées par Sass, avant de voir rapidement comment créer les nôtres.

Un fonction ?

Si vous avez un peu écouté en Maths au collège et/ou au lycée, vous devriez savoir ce qu’est une fonction mathématique. Du coup j’ai ressorti mon cahier de 3e :

Définition : Une fonction est un procédé par lequel on associe à un nombre donné (initial) un seul nombre correspondant.

Pour Sass, c’est un peu la même chose : on passe des données à la fonction (l’équivalent du nombre initial en Maths), elle fait ses calculs, et elle renvoie le résultat. Les données initiales, appelées arguments (comme pour les mixins) peuvent être des nombres, des couleurs, des chaînes de caractères, des listes, etc. tout comme le résultat.

Si, en plus d’écouter en Maths, vous avez déjà fait de la programmation, non seulement vous êtes formidable, mais en plus vous devriez savoir ce qu’est une fonction pour les concepteurs de Sass.

Un exemple ? Je vous propose d’essayer la fonction darken, inclue avec Sass, qui permet d’assombrir une couleur. Elle prend deux arguments : $color, la couleur de départ, et $amount le pourcentage d’assombrissement. Elle renvoie la couleur assombrie du pourcentage demandé :

La fonction darken prend deux arguments (#ff0000 et 10 %) et renvoie #cc0000.

On utilise la fonction darken ainsi :

1
    background-color: darken(#ff0000, 10%);

Comme attendu, ce code donne le CSS suivant :

1
    background-color: #cc0000;

Comme vous pouvez le remarquer, cette syntaxe est assez proche de celle utilisée par les mixins (les arguments entre parenthèses), sauf qu’on n’utilise pas @include. D’ailleurs, vous pouvez, comme pour les mixins, nommer vos arguments :

1
    background-color: darken($color: #ff0000, $amount: 10%);

Je pense que vous voyez bien en quoi cela peut nous être utile dans notre fil rouge. La couleur du hover de notre mixin bouton par exemple : il s’agit à chaque fois d’une version légèrement assombrie de la couleur d’arrière-plan de base. On peut tout à fait supprimer cet argument et le remplacer par un darken($background-color, 10%);. Notre mixin n’accepte donc désormais plus que deux arguments (ou plus, si vous avez ajouté la liste des polices).

Sass met à votre disposition tout un tas de fonctions très utiles, que nous allons voir plus en détail dans la suite de ce chapitre.

Quelques fonctions bien utiles

Commençons tout d’abord par voir quelques fonctions très utiles que Sass nous sert sur un plateau. Pour limiter l’effet "liste de courses", je les ai classées en différentes catégories.

Pour définir une couleur

Vous avez sans doute déjà utilisé rgb(), rgba(), hsl() ou hsla() pour définir une couleur dans une feuille de style. Sass considère que ce sont des fonctions qui renvoient une couleur. Cela veut dire qu’il les convertira automatiquement au format le plus adapté (le plus court) dans le fichier final.

Si vous ne connaissez pas le modèle HSL (Teinte Saturation Lumière), allez donc voir par ici ou par .

Pour jouer avec les nombres

De toutes les fonctions que Sass propose concernant les nombres, je pense que percentage($number) et round($number) sont les deux seules que vous devez retenir.

La première demande un nombre sans unité et retourne un pourcentage, comme dans cet exemple :

1
2
3
div {
  width: percentage(0.5); // 50%
}

Cependant, cela devient vraiment intéressant si vous avez des valeurs en pixels (tirées d’une maquette par exemple), car vous n’avez plus besoin de faire les calculs vous-mêmes :

1
2
3
div {
  width: percentage(200px/960px); // 20,8333% (vous aviez prévu de le faire de tête ?)
}

Si vous calculez l’ensemble des dimensions de vos blocs avec percentage() (en vous basant sur les dimensions dans la maquette statique), vous pouvez obtenir une grille fluide en un rien de temps.

Enfin, la fonction round() renvoie l’arrondi à l’unité du nombre donné. Très utile lorsque vous faites des divisions impliquant des pixels :

1
2
3
small {
  font-size: round(15px/2); // 8px
}

Bon, là je vous ai montré leur fonctionnement avec des valeurs inscrites "en dur", mais vous comprenez bien qu’utiliser des fonctions est surtout intéressant avec des variables. Ainsi, si vous changez la couleur principale de votre design, définie dans le fichier config.scss (ou quelque soit le nom que vous lui avez donné), les fonctions recalculeront à votre place les couleurs secondaires.

La palette du peintre

Voyons maintenant quelques unes des très nombreuses fonctions à notre disposition pour modifier les couleurs.

Inverse, Nuance de gris et Mélange

Commençons par celles qui changent radicalement une couleur :

1
2
3
invert($color);
grayscale($color);
mix($color1, $color2);

Les deux premières prennent une couleur pour seul argument :

  • invert() renvoie l’inverse ou négatif de la couleur donnée (ex: #ff0000 devient #00ffff),
  • grayscale()renvoie la nuance de gris correspondant à la couleur, c’est-à-dire son équivalent totalement dé-saturé (ex: #ff0000 devient #808080).

Enfin, la fonction mix()prend deux couleurs, et renvoie le mélange des deux :

1
2
3
4
h1{
  color: mix(#ff0000, #0000ff); // Renvoie #7f007f
  // Rouge + Bleu = Violet
}

A noter que mix() accepte un troisième argument optionnel en pourcentage, $weight, qui indique s’il faut plus de la première ou de la deuxième couleur.

Lumière, Saturation, Opacité

Continuons avec des fonctions qui proposent des altérations plus fines de lumière, de saturation ou d’opacité :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Lumière
lighten($color, $amount); // plus clair
darken($color, $amount); // plus sombre

// Saturation
saturate($color, $amount); // plus saturé
desaturate($color, $amount); // moins saturé

// Opacité
opacify($color, $amount); // plus opaque
transparentize($color, $amount); // moins opaque

Nous avons déjà vu darken() et, comme vous pouvez le constater, toutes ces fonctions demandent une couleur et un « pourcentage d’efficacité » de la transformation. Je pense que les noms sont assez explicites, donc plutôt que de vous décrire tout en détail, je vous propose plutôt un joli schéma bilan :

Schéma-bilan des fonctions qui modifient une couleur ($amount: 30%)

Les plus malins d’entre vous auront remarqué que le résultat de la fonction grayscale() correspond exactement à celui de desaturate() avec un $amount de 100%.

Jouons avec les listes

Avant de finir ce chapitre, je vous propose de regarder quelques fonctions qui permettent de modifier des listes.

La première est append($list, $val) et sert à ajouter un élément à la fin d’une liste :

1
2
$liste 1: "Source Sans Pro", Helvetica, Arial;
$liste2: append($font-list, sans-serif); // "Source Sans Pro", Helvetica, Arial, sans-serif

La deuxième est join($list1, list2) et assemble deux listes en une seule :

1
2
3
$liste1: 50px 2em;
$liste2: 10px 2em;
$liste3: join($liste1, $liste2); // 50px 2em 10px 2em

Sachez que append() et join() acceptent un troisième argument optionnel : $separator. Il permet de choisir le séparateur entre les éléments de la liste générée (entrez comma si vous voulez des virgules ou space si vous voulez des espaces). Par défaut, Sass choisit le séparateur de la/les listes passées en argument(s).

La troisième et dernière fonction est assez particulière mais très puissante. La fonction zip($lists...) accepte un ensemble de listes qu’elle va assembler en une unique liste multidimensionnelle (une liste de listes). Pour comprendre son fonctionnement, je vous propose d’essayer vous-même ce petit exemple :

1
2
3
4
5
6
$proprietes: color background-color width;
$durees: 1s 2s 10s;
$timing: linear ease-in-out ease;
div {
  transition: zip($proprietes, $durees, $timing);
}

Le code généré par Sass sera le suivant :

1
2
3
div {
  transition: color 1s linear, background-color 2s ease-in-out, width 10s ease;
}

Comme vous pouvez le constater, zip() a renvoyé une liste contenant 3 listes, qui contiennent chacune un élément de chaque liste passée en argument.

Et dans la pratique, ça sert à quoi ?

Excellente et pertinente question, brave lecteur ! J’ai eu personnellement à utiliser join() dans un cas précis il y a peu, qui pourrait se présenter à vous dans le futur. Bourbon, que nous verrons plus tard, propose la variable suivante :

1
2
3
4
5
6
$font-stack-georgia: (
  "Georgia",
  "Times",
  "Times New Roman",
  serif,
);

Elle fait partie de tout un lot de font stacks, c’est-à-dire des listes de polices prêtes à l’emploi. Personnellement, je cherchais à utiliser Bitter, qui est une très chouette police à empattement. Bourbon ne propose pas de font stack pour Bitter, mais comme elle se rapproche de Georgia, j’ai pu faire ceci, et le tour était joué :

1
$bitter: join(Bitter, $font-stack-georgia); // "Bitter", "Georgia", "Times",...

À côté de cela, ces trois fonctions (et plus particulièrement zip()) se révèleront particulièrement utiles lorsqu’on utilisera des boucles, dans les prochains chapitres. Voyons justement trois autres fonctions (et après, c’est fini, promis) dont nous auront besoin avec les boucles.

La première, qui n’est pas bien compliquée à appréhender, c’est la fonction length($list). Elle renvoie, comme son nom l’indique, la longueur de la liste, c’est-à-dire le nombre d’éléments contenus dans celle-ci. Ainsi, length($font-stack-georgia) renverra 4, car il y a 4 éléments dans cette liste.

Avant d’évoquer les deux autres, il est important que vous compreniez bien à quoi correspond l’indice ou index d’un item. Dans une liste, chaque élément a un index unique. Il s’agit tout bêtement de sa position dans la liste : le premier a l’index 1, le deuxième a l’index 2, etc.

Prenons l’exemple de notre liste $bitter. On obtient les couples index-valeur suivants :

Index 1 2 3 4 5
Valeur Bitter "Georgia" "Times" "Times New Roman" serif

La fonction nth($list, $n) permet de récupérer une valeur de la liste $list en donnant son index $n :

1
2
3
font-family: nth($bitter, 2); // "Georgia"
font-family: nth($bitter, 9); // Provoque une erreur, il n'y a pas assez d'items
font-family: nth($bitter, length($bitter)); // serif

Comme vous le voyez ligne 3, on peut obtenir le dernier élément d’une liste en combinant nth() et length().

La fonction index($list, $value) a le comportement exactement inverse. Elle renvoie l’index de la première apparition (en partant de la gauche) de la valeur $value dans la liste $list. Si la valeur donnée n’existe pas dans la liste, la fonction renvoie null. Ainsi, index($bitter, Georgia) renverra 2.

Si vous avez déjà fait un peu de programmation, vous remarquerez que, pour Sass, une liste commence à l’index 1 et non à l’index 0, au contraire de la plupart des langages de programmation.

Créer sa propre fonction

Je cherche une fonction très particulière que tu n’as pas présenté, comment faire ?

Il faut tout d’abord vérifier si cette fonction n’existe pas déjà. En effet, je n’ai pas la place (et ce serait sans intérêt) de décrire toutes les fonctions que Sass propose ici. Allez donc faire un tour sur la page de la documentation consacrée aux fonctions. Il y en a pour tous les goûts.

Si vous pensez avoir besoin d’une fonction qui n’existe pas encore, il va falloir la créer. Prenons pour exemple une fonction chargée de calculer la largeur d’une grille de mise en page, constituée de colonnes séparées par des gouttières. Elle aura trois arguments :

  • le nombre de colonnes $n
  • la largeur d’une colonne $colonne
  • la largeur d’un gouttière $gouttiere

Le nombre de gouttières est forcément égal à $n - 1. Voici donc le code de notre fonction :

1
2
3
@function largeur-grille($n, $colonne, $gouttiere){
  @return $n * $colonne + ($n - 1) * $gouttiere;
}

Comme vous le voyez, la syntaxe est proche de celle pour créer un mixin, à ceci près que l’on utilise la directive @function et que l’on doit appeler @return pour renvoyer le résultat de la fonction.

Maintenant, on peut utiliser notre fonction comme n’importe quelle autre :

1
2
3
div{
  width: largeur-grille(12, 60px, 20px); //940px
}

Sachez enfin que, comme pour les mixins, on a la possibilité de donner des valeurs par défauts aux arguments :

1
2
3
@function largeur-grille($n: 12, $colonne: 60px, $gouttiere: 20px){
  @return $n * $colonne + ($n - 1) * $gouttiere;
}

En résumé

  • Une fonction demande des arguments, fait des calculs et renvoie un résultat.
  • On peut créer ses propres fonctions avec la syntaxe @function.

Mémo des fonctions utiles

Catégorie

Nom(Arguments)

Résultat

Nombres

percentage($number)

Le pourcentage correspondant au nombre

round($number)

L’arrondi à l’unité

Couleurs

rgb($red, $green, $blue)

La couleur demandée

rgba($red, $green, $blue, $alpha)

La couleur demandée

hsl($hue, $saturation, $lightness)

La couleur demandée

hsla($hue, $saturation, $lightness, $alpha)

La couleur demandée

invert($color)

La couleur inverse (négatif)

grayscale($color)

La nuance de gris correspondant à la couleur

mix($color1, $color2)

Le mélange des deux couleurs

lighten($color, $amount)

La couleur plus claire (selon le %)

darken($color, $amount)

La couleur plus foncée (selon le %)

saturate($color, $amount)

La couleur plus saturée (selon le %)

desaturate($color, $amount)

La couleur moins saturée (selon le %)

opacify($color, $amount)

La couleur plus opaque (selon le %)

transparentize($color, $amount)

La couleur moins opaque (selon le %)

Listes

nth($list, $n)

La valeur dans la liste à l’index $n

index($list, $value)

L’index de la valeur dans la liste

length($list)

Le nombre d’éléments dans la liste

append($list, $val, $separator: auto)

La liste avec la valeur ajoutée à la fin

join($list1, $list2, $separator: auto)

Les deux listes assemblées en une seule

zip($lists...)

La liste multidimensionnelle tirée des listes

C’est la fin de ce dernier chapitre concernant les bases de Sass. Mais c’est pas fini ! Dans les prochains chapitres, il sera question d’héritage de classe, de boucles, de conditions et d’autres réjouissances.