Une barre latérale qui doit occuper toute la hauteur de l'écran moins la hauteur d'un en-tête fixe de 64 pixels ne se décrit pas facilement avec une seule unité : la hauteur de l'écran se pense en pourcentage, la hauteur de l'en-tête en pixels. Écrire une valeur qui combine les deux directement dans le CSS était impossible avant l'arrivée de calc().
La fonction résout exactement ce problème : elle laisse le navigateur faire le calcul lui-même, au moment où il affiche la page, avec des unités qui n'ont pourtant rien en commun au départ.
Définition
calc() est une fonction CSS qui accepte une expression mathématique et renvoie le résultat comme valeur d'une propriété. Elle peut mélanger des unités différentes dans une même expression, ce qu'aucune autre écriture CSS ne permet.
.barre-laterale {
height: calc(100vh - 64px);
}Le calcul n'a pas lieu à l'écriture du CSS, mais au moment où le navigateur affiche réellement la page, ce qui lui permet de réagir si la fenêtre change de taille : 100vh se recalcule à chaque redimensionnement, et la soustraction avec les 64px fixes suit automatiquement.
Les opérateurs et le piège des espaces
Les quatre opérateurs disponibles sont +, -, * et /, mais ils n'obéissent pas tous à la même règle d'espacement.
| Opérateur | Espace autour |
|---|---|
+ et - | Obligatoire des deux côtés |
* et / | Facultatif, mais recommandé pour la lisibilité |
width: calc(100% - 40px); /* correct */
width: calc(100% -40px); /* invalide, ignoré par le navigateur */
width: calc(100%-40px); /* invalide aussi */
width: calc(100% - 40px * 2); /* correct, espace facultatif autour de * */-, le navigateur ne sait plus s'il lit une soustraction ou un unique nombre négatif collé au précédent : la spécification tranche en faveur de la sécurité et rejette l'expression entière plutôt que de deviner. La propriété concernée est alors ignorée comme si calc() n'avait jamais été écrit.Imbriquer calc() et le combiner avec les variables
Une expression calc() peut en contenir une autre, et peut utiliser une Variable CSS comme n'importe quel autre nombre, ce qui permet de construire des échelles d'espacement cohérentes à partir d'une seule valeur de base.
:root {
--unite: 8px;
}
.carte {
padding: calc(var(--unite) * 2);
margin-bottom: calc(var(--unite) * 3 + 4px);
}Où calc() est acceptée
La fonction fonctionne partout où une longueur, un pourcentage, un nombre, un angle ou une durée est attendue : largeurs, marges, grid-template-columns, transform, transition-duration. Elle n'a en revanche aucun sens sur une valeur qui n'est pas numérique, comme display: flex ou un mot-clé de couleur nommée.
Un exemple concret : une barre latérale à largeur fixe
Une mise en page à deux colonnes, où la barre latérale garde toujours 280 pixels et où le contenu principal occupe le reste de l'écran, illustre bien l'intérêt de mélanger les unités dans un seul calcul plutôt que de fixer une largeur en pourcentage approximatif.
.contenu-principal {
width: calc(100% - 280px);
}Si la barre latérale change de largeur un jour, il suffit de modifier ce seul nombre dans l'expression calc() pour que le contenu principal s'ajuste automatiquement, sans recalculer un pourcentage à la main.
Questions fréquentes
calc() les uns dans les autres ?Oui, une expression calc() peut contenir une autre expression calc(), même si ce n'est presque jamais nécessaire dans la pratique : les parenthèses classiques à l'intérieur d'un seul calc() suffisent déjà à grouper les opérations.
calc(100% -20px) ne fonctionne pas alors que calc(100% - 20px) fonctionne ?Parce que sans espace, le navigateur ne distingue plus le signe moins d'une soustraction du signe moins d'un nombre négatif collé au précédent. La règle CSS impose un espace des deux côtés de + et de - précisément pour lever cette ambiguïté, ce qui rend l'erreur particulièrement facile à repérer une fois qu'on la connaît.
calc() pour calculer une couleur ?Pas directement sur une couleur nommée ou hexadécimale, mais oui sur un canal individuel dans une notation comme hsl(), par exemple pour éclaircir une teinte en calculant sa luminosité à partir d'une Variable CSS.