Dans ce chapitre, on va découvrir le principe des variables CSS. C'est une fonctionnalité très pratique qui permet d'éviter les répétitions et de centraliser certaines valeurs importantes comme les couleurs, les espacements ou les dimensions.
Le principe des variables CSS
En CSS, une variable s'appelle en réalité une propriété personnalisée. Pour la déclarer, on utilise un nom qui commence par deux tirets :
body {
--green: #2e5f3e;
}
Ici, --green devient une variable CSS contenant une couleur. Pour utiliser ensuite cette variable on passe par la fonction var() :
.logo {
color: var(--green);
}
À partir de là, si on change la valeur de --green, tous les endroits qui utilisent var(--green) se mettront à jour automatiquement.
Si on prend un exemple concret, dans notre site on utilise la même teinte de vert a plusieurs endroit, avec l'introduction d'une variable on peut éviter la répétition, et ainsi pouvoir modifier le thème de notre site plus facilement.
:root {
--primary: #2e5f3e;
}
.logo {
color: var(--primary);
}
.hero-title {
color: var(--primary);
}
.btn-fill {
background: var(--primary);
}
Où déclarer les variables ?
Techniquement, on peut déclarer une variable CSS dans n'importe quel sélecteur.
body {
--primary: #2e5f3e;
}
Cela fonctionne, mais en pratique, on préfère souvent regrouper les variables globales dans le sélecteur :root qui désigne l'élément racine du document (l'élément html)
:root {
--primary: #2e5f3e;
--secondary: #87a87b;
--background: #f8f4ee;
}
var() et la valeur de secours
Si une variable n'existe pas, la propriété qui l'utilise devient invalide et le navigateur retombe sur le comportement normal.
Pour éviter cela, on peut fournir une valeur par défaut :
.logo {
color: var(--primary, black);
}
Si --primary existe, elle est utilisée, sinon, le navigateur utilise black.
Les variables suivent la cascade
Comme les autres propriétés CSS, les variables obéissent à la cascade et à la spécificité. Cela signifie qu'on peut redéfinir une variable dans un sélecteur plus spécifique :
:root {
--primary: #2e5f3e;
}
.theme-pink {
--primary: pink;
}
Si un élément se trouve dans une zone qui porte la classe .theme-pink, la valeur de --primary changera dans cette zone uniquement.
Les variables ne servent pas qu'aux couleurs
On pense souvent aux variables pour les couleurs, mais elles peuvent contenir bien d'autres choses :
- des tailles
- des espacements
- des largeurs
- des hauteurs
- des durées
Par exemple :
:root {
--header-height: 80px;
}
.header {
height: var(--header-height);
}
Cela peut être très pratique quand une même valeur structurelle revient à plusieurs endroits.
Utiliser une variable dans une couleur partielle
Les variables peuvent aussi représenter une partie d'une valeur. Par exemple, avec un format comme oklch() ou hsl(), on peut stocker uniquement la teinte :
:root {
--hue: 318;
}
button {
background: oklch(62% 0.19 var(--hue));
color: oklch(96% 0.03 var(--hue));
}
L'intérêt est qu'en changeant uniquement --hue, on peut faire évoluer tout un ensemble de couleurs cohérentes.
C'est un usage plus avancé, mais très puissant quand on travaille sur un vrai système de design.
Les calculs avec calc()
Les variables deviennent encore plus intéressantes lorsqu'on les combine avec des calculs. Pour cela, on utilise la fonction calc() :
.hero {
height: calc(100vh - 80px);
}
Ici, on dit que la hauteur doit être égale à la hauteur de l'écran, moins 80px.
Cela peut servir, par exemple, à faire en sorte qu'un bandeau prenne tout l'écran sauf la hauteur du header.
Combiner calc() avec une variable
Plutôt que d'écrire la valeur directement, on peut utiliser une variable :
:root {
--header-height: 80px;
}
.header {
height: var(--header-height);
}
.hero {
height: calc(100vh - var(--header-height));
}
Dans ce cas :
- la hauteur du header est définie à un seul endroit
- le calcul du hero s'adapte automatiquement
Si la hauteur du header change, le reste suit.
Un autre cas concret : corriger une largeur
Prenons un champ de formulaire avec :
input {
width: 100%;
padding-inline: 1rem;
}
Le problème, c'est que 100% plus le padding peuvent provoquer un débordement.
On peut alors corriger avec :
input {
width: calc(100% - 2rem);
}
Cela permet de compenser le padding dans le calcul.
⚠️ Dans ce genre de cas, une autre solution aurait aussi été d'utiliser box-sizing: border-box;, souvent plus simple. Mais cet exemple montre bien dans quel type de situation calc() peut être utile.
Les fonctions min(), max() et clamp()
En plus de calc(), CSS propose aussi d'autres fonctions de calcul.
min()
min() permet de choisir la plus petite des valeurs proposées :
font-size: min(6rem, calc(1rem + 2vw));
Cela peut servir à plafonner une valeur dynamique.
max()
max() fait l'inverse et prend la plus grande valeur :
font-size: max(2rem, calc(1rem + 2vw));
Cela permet de garantir une valeur minimale.
clamp()
clamp() combine les deux approches :
font-size: clamp(2rem, calc(1rem + 2vw), 6rem);
La lecture est simple :
- valeur minimale :
2rem - valeur idéale :
calc(1rem + 2vw) - valeur maximale :
6rem
Cette fonction est particulièrement utile pour créer des tailles de texte fluides sans qu'elles deviennent trop petites ou trop grandes.
Un cas d'usage typique : les tailles de police fluides
Imaginons un grand titre :
.hero-title {
font-size: clamp(2rem, calc(1rem + 2vw), 6rem);
}
Dans ce cas :
- sur petit écran, la taille ne descendra pas sous
2rem - au milieu, elle évoluera avec la largeur de la fenêtre
- sur grand écran, elle ne dépassera pas
6rem
C'est un bon exemple de combinaison entre valeurs fixes, unités responsives et fonctions de calcul.