Les variables CSS, plus précisément appelées propriétés personnalisées CSS, sont disponibles dans Chrome 49. Ils peuvent être utiles pour réduire les répétitions dans le CSS, mais aussi pour des effets d'exécution puissants tels que le changement de thème et l'extension/le polyfilling potentiels de futures fonctionnalités CSS.
Encombrement CSS
Lors de la conception d'une application, il est courant de mettre de côté un ensemble de couleurs de la marque qui seront réutilisées pour assurer la cohérence de l'apparence de l'application. Malheureusement, répéter ces valeurs de couleur encore et encore dans votre CSS n'est pas seulement une corvée, mais aussi sujet à des erreurs. Si, à un moment donné, l'une des couleurs doit être modifiée, vous pouvez faire fi de la prudence et utiliser la commande "Rechercher et remplacer" pour toutes les choses, mais sur un projet suffisamment important, cela peut facilement devenir dangereux.
Récemment, de nombreux développeurs se sont tournés vers des préprocesseurs CSS tels que SASS ou LESS, qui résolvent ce problème grâce à l'utilisation de variables de préprocesseur. Bien que ces outils aient considérablement boosté la productivité des développeurs, les variables qu'ils utilisent présentent un inconvénient majeur : elles sont statiques et ne peuvent pas être modifiées au moment de l'exécution. L'ajout de la possibilité de modifier des variables au moment de l'exécution ouvre la porte à des éléments tels que la thématisation dynamique des applications, mais a également des conséquences majeures sur le responsive design et le potentiel de polyfiller de futures fonctionnalités CSS. Avec la sortie de Chrome 49, ces fonctionnalités sont désormais disponibles sous la forme de propriétés CSS personnalisées.
Propriétés personnalisées en résumé
Les propriétés personnalisées ajoutent deux nouvelles fonctionnalités à notre boîte à outils CSS:
- Possibilité pour un auteur d'attribuer des valeurs arbitraires à une propriété avec un nom choisi par l'auteur.
- La fonction
var()
, qui permet à un auteur d'utiliser ces valeurs dans d'autres propriétés.
Voici un exemple rapide pour illustrer
:root {
--main-color: #06c;
}
#foo h1 {
color: var(--main-color);
}
--main-color
est une propriété personnalisée définie par l'auteur avec une valeur de #06c. Notez que toutes les propriétés personnalisées commencent par deux tirets.
La fonction var()
récupère et se remplace par la valeur de la propriété personnalisée, ce qui donne color: #06c;
. Tant que la propriété personnalisée est définie quelque part dans votre feuille de style, elle doit être disponible pour la fonction var
.
La syntaxe peut sembler un peu étrange au premier abord. De nombreux développeurs se demandent : "Pourquoi ne pas simplement utiliser $foo
pour les noms de variables ?" L'approche a été choisie spécifiquement pour être aussi flexible que possible et permettre éventuellement l'utilisation de macros $foo
à l'avenir.
Pour en savoir plus, consultez ce post de l'un des auteurs de la spécification, Tab Atkins.
Syntaxe des propriétés personnalisées
La syntaxe d'une propriété personnalisée est simple.
--header-color: #06c;
Notez que les propriétés personnalisées sont sensibles à la casse. --header-color
et --Header-Color
sont donc des propriétés personnalisées différentes. Bien qu'elles puissent sembler simples à première vue, la syntaxe autorisée pour les propriétés personnalisées est en fait assez permissive. Par exemple, la propriété personnalisée suivante est valide:
--foo: if(x > 5) this.width = 10;
Bien que cela ne soit pas utile en tant que variable, car il serait non valide dans n'importe quelle propriété normale, il pourrait être lu et utilisé avec JavaScript au moment de l'exécution. Cela signifie que les propriétés personnalisées peuvent débloquer toutes sortes de techniques intéressantes qui ne sont actuellement pas possibles avec les préprocesseurs CSS actuels. Si vous pensez bâillement : "J'ai SASS, alors qui s'en soucie ?", alors je vous invite à y réfléchir à nouveau. Ce ne sont pas les variables que vous avez l'habitude d'utiliser.
La cascade
Les propriétés personnalisées suivent des règles en cascade standards. Vous pouvez donc définir la même propriété à différents niveaux de spécificité.
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
While I got red set directly on me!
<p>I’m red too, because of inheritance!</p>
</div>
Cela signifie que vous pouvez exploiter des propriétés personnalisées dans les requêtes multimédias pour faciliter le responsive design. Un cas d'utilisation peut être d'élargir les marges autour de vos principaux éléments de sectionnement à mesure que la taille de l'écran augmente:
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Il est important de noter que l'extrait de code ci-dessus n'est pas possible avec les préprocesseurs CSS actuels, qui ne peuvent pas définir de variables dans les requêtes multimédias. Cette capacité ouvre de nombreuses perspectives.
Il est également possible d'avoir des propriétés personnalisées qui dérivent leur valeur d'autres propriétés personnalisées. Cela peut être extrêmement utile pour la thématisation:
:root {
--primary-color: red;
--logo-text: var(--primary-color);
}
La fonction var()
Pour récupérer et utiliser la valeur d'une propriété personnalisée, vous devez utiliser la fonction var()
. La syntaxe de la fonction var()
se présente comme suit:
var(<custom-property-name> [, <declaration-value> ]? )
Où <custom-property-name>
est le nom d'une propriété personnalisée définie par l'auteur, comme --foo
, et <declaration-value>
est une valeur de remplacement à utiliser lorsque la propriété personnalisée référencée n'est pas valide. Les valeurs de remplacement peuvent être une liste séparée par des virgules, qui sera combinée en une seule valeur. Par exemple, var(--font-stack,
"Roboto", "Helvetica");
définit un remplacement de "Roboto", "Helvetica"
. N'oubliez pas que les valeurs abrégées, comme celles utilisées pour la marge et la marge intérieure, ne sont pas séparées par une virgule. Par conséquent, un remplacement approprié pour la marge intérieure se présente comme suit.
p {
padding: var(--pad, 10px 15px 20px);
}
À l'aide de ces valeurs de remplacement, un auteur de composant peut écrire des styles défensifs pour son élément:
/* In the component’s style: */
.component .header {
color: var(--header-color, blue);
}
.component .text {
color: var(--text-color, black);
}
/* In the larger application’s style: */
.component {
--text-color: #080;
/* header-color isn’t set,
and so remains blue,
the fallback value */
}
Cette technique est particulièrement utile pour thématiser les Web Components qui utilisent Shadow DOM, car les propriétés personnalisées peuvent traverser les limites d'ombre. Un auteur de composants Web peut créer une conception initiale à l'aide de valeurs de remplacement et exposer des "hooks" de thématisation sous la forme de propriétés personnalisées.
<!-- In the web component's definition: -->
<x-foo>
#shadow
<style>
p {
background-color: var(--text-background, blue);
}
</style>
<p>
This text has a yellow background because the document styled me! Otherwise it
would be blue.
</p>
</x-foo>
/* In the larger application's style: */
x-foo {
--text-background: yellow;
}
Lorsque vous utilisez var()
, vous devez faire attention à certains points. Les variables ne peuvent pas être des noms de propriétés. Par exemple :
.foo {
--side: margin-top;
var(--side): 20px;
}
Toutefois, cela n'équivaut pas à définir margin-top: 20px;
. À la place, la deuxième déclaration n'est pas valide et est rejetée en tant qu'erreur.
De même, vous ne pouvez pas (naïvement) créer une valeur dont une partie est fournie par une variable:
.foo {
--gap: 20;
margin-top: var(--gap)px;
}
Encore une fois, cela n'équivaut pas à définir margin-top: 20px;
. Pour créer une valeur, vous avez besoin d'un autre élément: la fonction calc()
.
Créer des valeurs avec calc()
Si vous n'avez jamais travaillé avec elle auparavant, la fonction calc()
est un petit outil pratique qui vous permet d'effectuer des calculs pour déterminer les valeurs CSS. Il est compatible avec tous les navigateurs modernes et peut être combiné à des propriétés personnalisées pour créer de nouvelles valeurs. Exemple :
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px); /* niiiiice */
}
Utiliser des propriétés personnalisées en JavaScript
Pour obtenir la valeur d'une propriété personnalisée au moment de l'exécution, utilisez la méthode getPropertyValue()
de l'objet CSSStyleDeclaration calculé.
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'
De même, pour définir la valeur de la propriété personnalisée au moment de l'exécution, utilisez la méthode setProperty()
de l'objet CSSStyleDeclaration
.
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');
Vous pouvez également définir la valeur de la propriété personnalisée pour qu'elle fasse référence à une autre propriété personnalisée au moment de l'exécution à l'aide de la fonction var()
dans votre appel à setProperty()
.
/* CSS */
:root {
--primary-color: red;
--secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');
Étant donné que les propriétés personnalisées peuvent faire référence à d'autres propriétés personnalisées dans vos feuilles de style, vous pouvez imaginer que cela peut entraîner toutes sortes d'effets d'exécution intéressants.
Prise en charge des navigateurs
Actuellement, Chrome 49, Firefox 42, Safari 9.1 et iOS Safari 9.3 sont compatibles avec les propriétés personnalisées.
Démo
Essayez l'exemple pour découvrir toutes les techniques intéressantes que vous pouvez désormais exploiter grâce aux propriétés personnalisées.
Documentation complémentaire
Pour en savoir plus sur les propriétés personnalisées, Philip Walton de l'équipe Google Analytics a rédigé un article expliquant pourquoi il est enthousiaste à l'égard des propriétés personnalisées. Vous pouvez également suivre leur progression dans d'autres navigateurs sur chromestatus.com.