Sass (Syntactically Awesome Stylesheets) est un langage de génération de CSS.
Sass ajoute des fonctionnalités à CSS, comme l’ajout de variables, de fonctions, d’opérations mathématiques. Tout CSS est du code Sass valide.
Les fichiers Sass une fois compilés sont des fichiers CSS classiques.
CSS est un langage conçu pour être simple: on applique des propriétés/valeurs aux éléments HTML pour modifier leur apparence. Mais cette simplicité peut devenir problématique
Il existe deux extensions de fichiers Sass pour deux variations de la syntaxe :
.scss
est l’extension de fichier par défaut
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
.sass
est une variation indentée et sans point-virgule
$font-stack: Helvetica, sans-serif
$primary-color: #333
body
font: 100% $font-stack
color: $primary-color
Toutes les fonctionnalités sont identiques entre un fichier .scss et un fichier .sass, seule change la présentation.
Pour installer un préprocesseur Sass, voir la doc Sass.
On peut également utiliser Webpack.
Les commentaires Sass ne sont pas présents dans le fichier compilés.
// single line comment
L’instruction @import
permet de modulariser le CSS.
Bien qu’elle existe officiellement dans la syntaxe CSS, cette instruction a historiquement été évitée à cause du manque de performance qu’elle implique (le fait que le navigateur ait à télécharger les fichiers CSS importés ralentit le chargement de la page).
Avec Sass, l’instruction @import
est executée au moment de la compilation, les fichiers sont directement ajoutés au fichier CSS généré, ce qui résout ce problème.
L’extension du fichier est optionnelle, les fichiers .scss
et .sass
seront cherchés.
@import buttons
Pour éviter que les fichiers Sass importés dans d’autres fichiers soient compilés en fichier CSS par le compilateur, on préfixe le nom du fichier par _
(underscore).
Ces fichiers peuvent être importés mais ne ils ne générent de fichier CSS eux-même.
_buttons.scss
Les sélecteurs peuvent être imbriqués
SCSS | CSS généré |
---|---|
|
|
Certaines propriétés peuvent également être imbriquées
SCSS | CSS généré |
---|---|
|
|
Le symbole &
permet de désigner le sélecteur parent, par exemple pour ajouter des conditions à la sélection
SCSS | CSS généré |
---|---|
|
|
Des sélecteurs peuvent être ajoutés devant &
SCSS | CSS généré |
---|---|
|
|
Pour plus de lisibilité et de performance, il est préférable d’éviter d’imbriquer plus de 3 ou 4 niveaux (refactoriser le code si nécessaire).
Les variables Sass commençent par $
, par exemple $base
.
$base: #777777;
.sidebar {
border: 1px solid $base;
}
Si une variable est définie deux fois, la deuxième assignation écrase la première. Pour éviter ça, le flag !default
peut être utilisé.
$title: "My Blog";
$title: "About Me" !default;
h2:before {
content: $title;
}
C’est particulièrement utile lorsqu’on utilise des partials, lesquelles peuvent définir ainsi des variables par défaut que l’on peut redéfinir dans le fichier qui l’inclut.
$radius: 5px;
@import "buttons";
Plusieurs types de données sont supportés
Booléens |
|
---|---|
Nombres | Avec ou sans unités
|
Couleurs |
|
Chaînes de caractère | Avec ou sans quotes
|
Listes |
|
Valeur vide |
|
Les variables définies à l’intérieur d’un bloc ne sont pas utilisables à l’extérieur de ce bloc
p {
$border: #ccc;
border-top: 1px solid $border;
}
En revanche on peut modifier la valeur des variables définies à l’extérieur du bloc pour les sélecteurs qui suivent.
$color: #777;
.sidebar {
$color: #222;
background: $color;
}
p {
color: $color; // vaut #222
}
La syntaxe #{$variable}
permet d’utiliser la valeur de la variable dans un nom de propriété ou dans une valeur.
$side: top;
sup {
position: relative;
#{side}: -0.5em;
}
.callout-#{$side} {
background: #777;
}
Des opérations mathématiques peuvent être effectuées sur les valeurs.
Par défaut, Sass retourne jusqu’à 5 chiffres après la virgule.
Opérateur | Description |
---|---|
+ | addition |
- | subtraction |
* | multiplication |
/ | division |
% | modulo |
Si les unités diffèrent entre les valeurs, Sass essaie de calculer la valeur en fonction de l’unité la plus à gauche.
font-size: 10px + 4pt; // 15.33333px;
Le symbole /
(slash) est une syntaxe CSS valide. Pour que le compilateur considère ce symbole comme une opération mathématique et non comme un élément de syntaxe, il faut soit
$size / 10
(100px / 20)
20px * 5 / 2
L’opérateur +
(plus) permet de concaténer des chaînes de caractères.
La chaîne de caractères qui en résulte aura des quotes selon la chaîne de caractères la plus à gauche.
$family: "Helvetica " + "Neue"; // "Helvetica Neue"
$family: 'sans-' + serif; // "sans-serif"
$family: sans- + 'serif'; // sans-serif
Pour concaténer une variable, utiliser l’expansion
$family: "#{$font}, serif";
Les mixins permettent d’inclure des propriétés CSS à l’intérieur d’un sélecteur, ce qui permet d’éviter les répétitions. Attention à bien définir les mixins avant de les utiliser, particulièrement avec des imports de fichiers.
On les définit avec @mixin
et on les appele avec @include
.
SCSS | CSS généré |
---|---|
|
|
Les mixins peuvent prendre des arguments
@mixin box-sizing($x) {
-webkit-box-sizing: $x;
-moz-box-sizing: $x;
box-sizing: $x;
}
.btn-a {
@include box-sizing(border-box);
border: 1px solid #ccc;
}
On peut définir des valeurs par défaut aux arguments
@mixin box-sizing($x: border-box) {
-webkit-box-sizing: $x;
-moz-box-sizing: $x;
box-sizing: $x;
}
.btn-a {
@include box-sizing;
border: 1px solid #ccc;
}
Les arguments sont séparés par des virgules. Les arguments optionnels (avec une valeur par défaut) sont placés à la fin de la liste.
@mixin button($radius, $color: #000) {
border-radius: $radius;
color: $color;
}
Au moment d’appeler la mixin, les valeurs peuvent être passées sous forme de clé/valeur. Cela permet d’éviter les confusions (quel argument vaut quoi).
@include button($color: #777, $radius: 5px);
Suffixer ...
à un argument crée un argument qui prend une liste de valeurs.
@mixin transition($val...) {
-webkit-transition: $val;
-moz-transition: $val;
transition: $val;
}
.btn-a {
@include transition(color 0.3s ease-in, background 0.5s ease-out);
}
L’inverse est également possible, on peut éclater une liste en plusieurs paramètres.
@mixin button($radius, $color) {
border-radius: $radius;
color: $color;
}
$properties: 4px, #000;
.btn-a {
@include button($properties...);
}
Avec l’instruction @extend
, Sass combine des sélecteurs définis à des endroits différents.
SCSS | CSS généré |
---|---|
|
|
Avec @extend
, si B extend A, alors toute propriété de A (et de ses descendants) est également appliquée à B. Cela peut créer du code inutile.
Pour éviter ça, on peut créer des placeholders, qui fonctionnent un peu comme des sélecteurs abstraits (des sélecteurs qui ne générent pas de bloc CSS par eux-mêmes mais que l’on peut hériter).
%btn {
background: #777;
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
.btn-a {
@extend %btn;
}
.btn-b {
@extend %btn;
background: #ff0;
}
.sidebar .btn-a {
text-transform: lowercase;
}
Les fonctions permettent de calculer des valeurs.
Les arguments des fonctions ont les mêmes règles que les mixins.
Il est obligatoire d’appeler une fonction avec des parenthèses, même quand aucun paramètre n’est passé.
@function fluidize() {
@return 35%;
}
.sidebar {
width: fluidize();
}
@function fluidize($target, $context) {
@return ($target / $context) * 100%;
}
.sidebar {
width: fluidize(350px, 1000px);
}
Sass définit plusieurs fonctions natives. Elles sont appelées de la même manière que les fonctions crées manuellement.
round($number) | Arrondi à l'entier le plus proche |
---|---|
ceil($number) | Arrondi à l'entier supérieur |
floor($number) | Arrondi à l'entier inférieur |
abs($number) | Retourne la valeur absolue |
min($list) | Retourne la valeur maximale |
max($list) | Retourne la valeur minimale |
percentage($number) | Convertit en pourcentages |
h2 {
line-height: ceil(1.2);
}
.sidebar {
width: percentage(350px/1000px);
}
On peut utiliser les opérateurs sur les couleurs
$color-base: #333333;
.addition {
background: $color-base + #112233;
}
.subtraction {
background: $color-base - #112233;
}
.multiplication {
background: $color-base * 2;
}
.division {
background: $color-base / 2;
}
Ou faire appel à des fonctions pour éclaircir, assombrir, changer la saturation, etc. Voir la doc pour la liste complète.
$color: #333333;
.alpha {
background: rgba($color, 0.8);
}
.lighten {
color: lighten($color, 20%);
}
.darken {
color: darken($color, 20%);
}
.saturate {
color: saturate($color, 20%);
}
.desaturate {
color: desaturate($color, 20%);
}
.mix-a {
color: mix(#ffff00, #107fc9); // 50% yellow, 50% blue
}
.mix-b {
color: mix(#ffff00, #107fc9, 30%); // 30% yellow, 70% blue
}
.grayscale {
color: grayscale($color);
}
.invert {
color: invert($color);
}
.complement {
color: complement($color);
}
Le @if
permet d’ajouter des propriétés sous condition.
Les opérateurs disponibles sont ==
, !=
, >
, >=
, <
, <=
.
$theme: dark;
header {
@if theme == dark {
background: #000;
} @else if $theme == pink {
background: pink;
} @else {
background: #fff;
}
}
@each
permet d’itérer sur une liste d’items
$authors: nick aimee dan drew;
@each $author in $authors {
.author-#{$author} {
background: url(author-#{author}.jpg);
}
}
@each $color in blue, red, green {
.#{$color}-text {color: $color;}
}
$colors: (color1: blue, color2: red, color3: green);
@each $key, $color in $colors {
.#{$key}-text {color: $color;}
}
@for
permet d’effectuer un boucle de i à n (inclus).
.item {
position: absolute;
right: 0;
@for $i from 1 through 3 {
&.item-#{$i} {
top: $i * 30px;
}
}
}
Avec @while
on met à jour l’index manuellement
.item {
position: absolute;
right: 0;
$i: 1;
@while $i < 4 {
&.item-#{$i} {
top: $i * 30px;
}
$i: $i + 1;
}
}
Les media queries peuvent être imbriquées à l’intérieur d’un bloc CSS.
Attention
@media
ne sera pas factorisé dans le CSS généré, il est donc souvent préférable de le séparer complètement@media
ne peuvent pas être utilisées à l’intérieur. Par exemple, on ne peut pas utiliser de @extend
dans un bloc mediaSCSS | CSS généré |
---|---|
|
|
On peut utiliser une mixin et passer le contenu du bloc, ce qui permet de mettre en commun les conditions media utilisées (min-width, max-wdith, etc).
@mixin respond-to($media) {
@if $media == desktop {
@media (min-width: 960px) {
@content;
}
}
}
.sidebar {
border: 1px solid #ccc;
@include respond-to(desktop) {
float: right;
width: 30%;
}
}