La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Que peut-on mettre dans une variable CSS?

par Will Boyd, 26 février 2023, css, article original paru le 6 décembre 2020 dans Codersblock

Will Boyd fait un point complet sur les variables CSS et tout ce qu'on peut faire avec. Bluffant, comme d'habitude !


Les variables CSS (également appelées propriétés personnalisées CSS, custom properties en anglais) peuvent contenir toutes sortes de choses. Certaines n'étaient pas évidentes pour moi, c'est pourquoi j'ai décidé d'écrire cet article.

Pour être clair, cet article se concentre sur ce que vous pouvez mettre dans une variable CSS — avec une démonstration d'animation vers la fin parce que je ne pouvais pas m'en empêcher. Si vous recherchez des conseils plus généraux sur l'utilisation des variables CSS, il existe d'autres excellents articles pour cela.

des cercles de couleur concentriques

Valeurs unitaires et un peu de maths

Commençons par le plus simple. Il est courant de mettre des valeurs numériques avec des unités dans une variable CSS. Celles-ci sont formellement connues sous le nom de dimensions.

:root {
  --nice-padding: 20px;
  --decent-font-size: 1.25rem;
}

article {
  padding: var(--nice-padding);
  font-size: var(--decent-font-size);
}

Les variables peuvent contenir les résultats de calculs impliquant d'autres variables via calc().

:root {
  --image-width: 800px;

  /* calculate height to preserve a 4:3 aspect ratio */
  --image-height: calc(var(--image-width) / (4 / 3));
}

img {
  width: var(--image-width);
  height: var(--image-height);
}

De même, les variables peuvent être utilisées avec les fonctions CSS intégrées.

:root {
  --min: 1rem;
  --max: 4rem;
  --clamped-font-size: clamp(var(--min), 2.5vw, var(--max));
}

p {
  font-size: var(--clamped-font-size);
}

Valeurs numériques sans unité

Les variables peuvent également contenir des valeurs numériques sans unité. Certaines propriétés CSS utilisent directement ces valeurs.

:root {
  --obnoxiously-big-number: 9001;
}

.important-modal {
  z-index: var(--obnoxiously-big-number);
}

Mais d'autres fois, vous pouvez vouloir appliquer des unités à ces valeurs. Ça peut se faire très simplement avec une multiplication dans une expression calc().

:root {
  --magic-number: 41;
}

.crazy-box {
  width: calc(var(--magic-number) * 1%);
  padding: calc(var(--magic-number) * 1px);
  transform: rotate(calc(var(--magic-number) * 1deg));
}

Des trucs non numériques

Les variables CSS ne sont pas uniquement destinées aux chiffres. Elles peuvent contenir des mots-clés prédéfinis que les propriétés reconnaissent.

:root {
  --bullets: circle;
  --casing: uppercase;
}

ul {
  list-style-type: var(--bullets);
  text-transform: var(--casing);
}

Il existe également des identifiants personnalisés qui pointent vers des éléments que vous avez définis et nommés, comme un nom d'animation ou une zone de grille, comme indiqué ci-dessous.

:root {
  --layout-position: center-stage;
}

body {
  grid-template-areas: 'left center-stage right';
}

main {
  grid-area: var(--layout-position);
}

Chaînes de contenu

Les pseudo-éléments ::before et ::after utilisent la propriété content pour afficher, eh bien... du contenu. Ce contenu peut être un certain nombre de choses différentes, mais il s'agira souvent de chaînes de caractères (string).

Le CSS suivant montre que le contenu est alimenté par des variables de type string. Vous pouvez également voir comment concaténer des variables de type string avec d'autres chaînes de caractères et comment extraire une valeur de type string d'un attribut avec attr().

:root {
  --open: '(';
  --close: ')';
  --heading-hint: ' ' var(--open) 'this is a heading' var(--close);
  --link-hint: ' ' var(--open) attr(href) var(--close);
}

h1::after {
  content: var(--heading-hint);
}

a::after {
  content: var(--link-hint);
}

Voici une démo pour vous montrer le résultat.

Images

Les variables CSS peuvent également contenir des images. Les images peuvent également être affichées dans le contenu, mais on les voit sans doute plus couramment dans background-image.

:root {
  /* image from an external URL (PNG in this case) */
  --image-from-somewhere: url(https://codersblock.com/assets/images/logo.png);

  /* image from embedded data (SVG in this case) */
  --image-embedded: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256c0 136.966 111.033 248 248 248s248-111.034 248-248S392.966 8 256 8 8 119.033 8 256zm248 184V72c101.705 0 184 82.311 184 184 0 101.705-82.311 184-184 184z'%3E%3C/path%3E%3C/svg%3E");
}

.a {
  background-image: var(--image-from-somewhere);
}

.b::after {
  content: var(--image-embedded);
}

Cela vous permet de vous débarrasser des URL d'images longues et difficiles à manier et d'utiliser des noms de variables plus courts lorsque c'est nécessaire.

Abréviations

Une variable CSS peut être utilisée comme une valeur unique dans un raccourci, ou comme le racourci entier lui-même. Les deux éléments conteneurs ci-dessous auront le même padding.

:root {
  --top-padding: 60px;
  --all-padding: 60px 20px 40px 10px;
}

.container {
  padding: var(--top-padding) 20px 40px 10px;
}

.another-container {
  padding: var(--all-padding);
}

J'ai trouvé intéressant que les variables CSS puissent également contenir un segment partiel d'un raccourci formé de plusieurs valeurs.

Listes

Certaines propriétés, comme background et box-shadow, peuvent prendre une liste d'éléments. Vous pouvez utiliser une variable CSS comme un seul élément de la liste, une sous-liste de la liste ou la liste entière.

Voici quelques exemples de mélanges de listes box-shadow et de variables CSS. J'ai également glissé un exemple de mise en place d'une liste de couleurs dans une variable CSS pour l'utiliser dans un dégradé linéaire, car vous pouvez tout à fait le faire !

/*
  quick reminder of the anatomy of a box-shadow!
  box-shadow: <x-offset> <y-offset> <blur> <spread> <color>;
*/

:root {
  --single-shadow: 0 0 0 40px #355c7d;
  --multi-shadow: 0 0 0 60px #f67280, 0 0 0 80px #6c5b7b;
  --gradient-colors: #f1bbba, #ece5ce, #c5e0dc;
}

.a {
  box-shadow: 0 0 0 20px #60b99a, var(--single-shadow);
}

.b {
  box-shadow: var(--multi-shadow);
}

.c {
  box-shadow: 0 0 0 20px #60b99a, var(--single-shadow), var(
      --multi-shadow
    );
}

body {
  background-image: linear-gradient(45deg, var(--gradient-colors));
}

Et voici une démo pour voir ce que ça peut donner :

voir CSS Variables with Shadow Lists de lonekorean dans CodePen

Couleurs

Ah ! on ne peut pas oublier les couleurs ! Les variables CSS fonctionnent très bien pour les couleurs et il est très courant de les voir utilisées pour définir un thème de couleurs facile à consommer dans tout un site.

@media (prefers-color-scheme: light) {
  :root {
    --color-text: #233742;
    --color-links: #d80b77;
    --color-bg: white;
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-text: white;
    --color-links: #b4cddd;
    --color-bg: #233742;
  }
}

body {
  color: var(--color-text);
  background-color: var(--color-bg);
}

a {
  color: var(--color-links);
}

Vous pouvez également placer des valeurs de paramètres de couleur distinctes dans des variables CSS, puis les combiner en une couleur à l'aide de rgb()/rgba() et hsl()/hsla(). Voici un exemple utilisant rgb().

:root {
  --red: 216;
  --green: 11;
  --blue: 119;
}

a {
  color: rgb(var(--red), var(--green), var(--blue));
}

Réunir le tout avec l'animation

Peut-on mettre une valeur animée dans une variable CSS ? La réponse est : c'est compliqué !

Par défaut, la plupart du temps non. Certains navigateurs afficheront un seul saut discret de la valeur de départ à la valeur d'arrivée. D'autres navigateurs ne feront rien. Dans tous les cas, vous n'obtiendrez pas d'animation lisse et interpolée.

Le problème est que votre navigateur ne sait pas comment animer vos variables inventées. Mais bonne nouvelle ! Vous pouvez résoudre ce problème grâce à l'API Propriétés et Valeurs. Elle fait partie de Houdini et fonctionne actuellement dans Chrome, Edge et Opera, et d'autres navigateurs devraient suivre.

Voici comment cela fonctionne. Tout d'abord, déclarez vos propriétés personnalisées.

@property --red {
  syntax: '<integer>';
  inherits: true;
  initial-value: 0;
}
@property --green {
  syntax: '<integer>';
  inherits: true;
  initial-value: 0;
}
@property --blue {
  syntax: '<integer>';
  inherits: true;
  initial-value: 0;
}

Il s'agit de dire à votre navigateur "hé, voici quelques variables, ce sont des entiers qui ont la valeur 0 par défaut". Ensuite, votre navigateur peut dire "oh les entiers, super, je sais comment les animer". Et maintenant, nous sommes prêts pour l'animation.

@keyframes red-fade {
  50% {
    --red: 255;
  }
}
@keyframes green-fade {
  50% {
    --green: 255;
  }
}
@keyframes blue-fade {
  50% {
    --blue: 255;
  }
}

:root {
  animation: red-fade 16s, green-fade 14s, blue-fade 12s;
  animation-iteration-count: infinite;
}

Dans le CSS ci-dessus, il y a une animation keyframe pour chaque variable allant de 0 (la valeur initiale initial-value que nous avons déclarée) à 255 et inversement. Ces valeurs sont animées sur l'élément :root et tous les éléments enfants peuvent les utiliser car nous avons déclaré les variables avec inherits : true.

.swatch {
  background-color: rgb(var(--red), var(--green), var(--blue));
}

Et avec ça, nous avons 3 variables CSS animées indépendamment qui sont combinées ensemble via rgb() pour créer une background-color en constante évolution. Pas de JavaScript. Super !

voir CSS Variables Color Animation de lonekorean dans CodePen

Il se passe en fait beaucoup de choses dans cette démo. De multiples animations sont alimentées par ce trio de variables CSS animées (--red, --green, --blue). Décomposons le tout.

Tout d'abord, la grande palette de couleurs RGB. Nous en avons déjà parlé.

Ensuite, les indicateurs qui montent et descendent au-dessus des barres de couleur. Ils sont positionnés en convertissant les variables CSS en valeurs px négatives. Par exemple, voici le rouge.

.red .indicator {
  transform: translateY(calc(var(--red) * -1px));
}

Troisièmement, les chiffres affichés sous les barres de couleur. Celui-ci est intéressant. Comme mentionné précédemment, vous pouvez utiliser content pour afficher des chaînes de caractères, mais cela ne fonctionnera pas avec nos variables entières. Cependant, les compteurs CSS fonctionnent avec des valeurs entières et peuvent être affichés tout comme une chaîne de caractères avec du contenu.

.red .value::before {
  /* in goes an integer variable */
  counter-reset: color-value var(--red);

  /* out comes a string-like counter value */
  content: counter(color-value);
}

En gros, nous abusons des compteurs CSS pour convertir un nombre entier en chaîne de caractères. Que du plaisir.

Valeurs à l'échelle du CSS

Les propriétés personnalisées suivent les mêmes règles que les propriétés intégrées en ce qui concerne la cascade et l'héritage. Vous pouvez utiliser les mêmes valeurs spéciales CSS que sont initial, inherit, unset et revert sur les variables CSS pour contrôler ce qui y est finalement placé.

Au revoir

Du point de vue de la syntaxe, les variables CSS sont "extrêmement permissives". Il y a certainement d'autres types de choses que vous pouvez y mettre que je n'ai pas spécifiquement couvertes, mais j'espère en avoir montré suffisamment pour vous donner une idée des possibilités. De plus, nous avons eu l'occasion de jouer avec des couleurs animées, donc c'était amusant.

Autres ressources externes

Articles de Will Boyd traduits dans La Cascade

Voir la page de Will Boyd et la liste de ses articles dans La Cascade.
Article original paru le 6 décembre 2020 dans Codersblock
Traduit avec l'aimable autorisation de Codersblock et de Will Boyd.
Copyright Codersblock © 2020