Que sont les variables CSS ?
Les variables CSS, officiellement appelées custom properties, sont des valeurs que vous définissez une seule fois et que vous référencez n’importe où. Elles ressemblent à des propriétés ordinaires mais commencent par --, et vous les utilisez avec la fonction var().
/* tokens.css */
:root {
--color-brand: #2563eb;
--radius: 0.5rem;
--space-4: 1rem;
}
.button {
background: var(--color-brand);
border-radius: var(--radius);
padding: var(--space-4) calc(var(--space-4) * 1.5);
}
La différence fondamentale avec une variable de préprocesseur est que les custom properties font partie de la cascade du navigateur. Elles sont héritées, peuvent être limitées à une portée spécifique (scoped) et peuvent être modifiées au moment de l’exécution (runtime). Cela en fait la solution naturelle pour la gestion des thèmes et des design tokens.
Déclaration et utilisation
Déclarez une propriété personnalisée avec un nom commençant par deux tirets et n’importe quelle valeur valide.
/* declare.css */
:root {
--gap: 1.5rem;
--shadow: 0 1px 2px rgb(0 0 0 / 0.08);
--font-sans: "Inter", system-ui, sans-serif;
}
.card {
gap: var(--gap);
box-shadow: var(--shadow);
font-family: var(--font-sans);
}
Les valeurs peuvent être presque n’importe quoi : des couleurs, des longueurs, des ombres, des piles de polices, des dégradés ou même des fragments de valeur. Comme elles sont substituées avant que la propriété ne soit analysée, elles peuvent être combinées avec calc().
La cascade et l’héritage
Les propriétés personnalisées suivent les règles habituelles du CSS. Une déclaration sur un élément est héritée par ses descendants, et c’est la déclaration la plus proche qui l’emporte.
/* scope.css */
:root {
--accent: #2563eb;
}
.sidebar {
--accent: #f97316;
}
.sidebar a {
color: var(--accent); /* orange inside the sidebar */
}
C’est ce qui rend le scoping si puissant : vous pouvez modifier le thème d’un composant ou d’une section sans toucher aux tokens globaux. C’est également pour cette raison que définir des tokens sur :root les rend disponibles partout.
Valeurs de repli (Fallbacks)
var() accepte une valeur de repli (fallback) comme second argument, utilisée lorsque la propriété est manquante ou invalide.
/* fallback.css */
.button {
color: var(--button-color, #ffffff);
background: var(--button-bg, var(--color-brand, #2563eb));
}
Les fallbacks sont utiles pour les composants réutilisables qui doivent fonctionner même lorsque les tokens ne sont pas définis, et ils peuvent être imbriqués. Utilisez-les avec parcimonie : si un token doit impérativement exister, définissez-le clairement plutôt que de masquer le problème.
Le thémage
Le thémage est le cas d’utilisation phare. Remplacez un ensemble de variables et tout un sous-arbre se met à jour.
/* theme.css */
:root {
--bg: #ffffff;
--surface: #f8fafc;
--text: #0f172a;
--border: #e2e8f0;
}
[data-theme="dark"] {
--bg: #0b0d0c;
--surface: #14161a;
--text: #e5e7eb;
--border: #26292e;
}
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--surface);
border: 1px solid var(--border);
}
Basculez un attribut data-theme sur l’élément racine et toute la page change de thème instantanément, sans duplication de règles. Vous pouvez également limiter un thème à un composant, permettant ainsi d’afficher une carte sombre sur une page claire.
Valeurs dynamiques avec JavaScript
Comme les propriétés personnalisées résident dans le DOM, vous pouvez les lire et les modifier via JavaScript.
// progress.js
const bar = document.querySelector(".progress");
function setProgress(percent) {
bar.style.setProperty("--progress", `${percent}%`);
}
setProgress(72);
/* progress.css */
.progress__fill {
width: var(--progress, 0%);
}
C’est ainsi que sont généralement conçues les barres de progression, les interactions de glisser-déposer, les effets de suivi du curseur et les commutateurs de thème. La valeur reste dans le CSS et JavaScript ne fait que mettre à jour un nombre.
Propriétés typées avec @property
Par défaut, les propriétés personnalisées sont des chaînes de caractères non typées, le navigateur ne peut donc pas les interpoler. La règle @property permet d’enregistrer un type, une valeur initiale et un comportement d’héritage.
/* property.css */
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--angle), #2563eb, transparent);
animation: rotate 1s linear infinite;
}
@keyframes rotate {
to { --angle: 360deg; }
}
Une fois le type enregistré, la propriété devient animable et le navigateur valide la valeur, ce qui permet d’éviter toute une catégorie de bugs.
Bonnes pratiques
- Définissez des tokens globaux sur
:rootet utilisez-les partout. - Nommez vos tokens selon leur usage (
--color-text) et non selon leur apparence (--gray-900). - Surchargez les variables pour les thèmes et les variantes de composants plutôt que de dupliquer les règles.
- Prévoyez des valeurs de secours (fallbacks) pour les composants réutilisables susceptibles de s’exécuter sans tokens.
- Mettez à jour les variables via JavaScript plutôt que d’écrire des styles inline partout.
- Enregistrez les propriétés animables avec
@property. - Gardez un ensemble de tokens restreint et cohérent.
Erreurs courantes
- S’attendre à ce que les propriétés personnalisées se comportent comme des variables Sass lors de la compilation.
- Utiliser des noms vagues qui rendent l’ensemble de tokens difficile à maintenir.
- Définir chaque valeur comme une variable, au détriment de la lisibilité.
- Oublier que les valeurs ne sont pas typées, à moins d’être enregistrées avec
@property. - Surcharger les tokens globalement alors que seul un sous-arbre devrait être modifié.
- Stocker des secrets ou des données utilisateur dans des variables CSS, lesquelles sont visibles dans le DOM.
Et après ?
Les propriétés personnalisées sont le ciment d’une feuille de style maintenable. Appliquez-les à votre mise en page avec le Responsive Design, animez les propriétés typées avec les Animations & Transitions, et comprenez la cascade qui les régit dans le guide CSS. Pour les variables de build qui les complètent, consultez la section Sass.