Skip to main content

Chapitre 85 : Interpolation et animations de variables CSS

Concepts clés : Utilisation de @property pour animer des valeurs numériques complexes et l'interpolation mathématique des variables CSS.

L'Interpolation des Variables CSS

1. Quoi

L'interpolation est le processus mathématique consistant à calculer des valeurs intermédiaires entre deux points donnés. En CSS classique, les variables (Custom Properties) sont traitées par le navigateur comme des chaînes de caractères (strings).

Lorsqu'on tente d'animer une variable standard, le navigateur ne sait pas comment "calculer" le chemin entre deux valeurs. Par exemple, passer de --my-color: red à --my-color: blue fonctionne car le navigateur reconnaît que ces valeurs appartiennent au type "couleur". Cependant, passer de --my-angle: 0deg à --my-angle: 360deg via une variable CSS standard échouera : le navigateur verra un changement de texte et effectuera un saut brutal (on/off) sans transition fluide.

L'introduction de la règle @property (via l'API CSS Properties and Values) permet de typer explicitement une variable. En définissant un type (comme <angle>, <color>, <number>, ou <percentage>), on indique au moteur de rendu comment interpoler mathématiquement la valeur durant une transition ou une animation.

2. Pourquoi

Dans un projet professionnel de haut niveau, l'interpolation des variables est indispensable pour :

  1. Animations de Gradients : Les gradients ne sont pas des couleurs, mais des images (image type). On ne peut pas animer un linear-gradient nativement. En typant les couleurs ou les angles à l'intérieur du gradient via @property, on peut créer des transitions de couleurs fluides dans un arrière-plan.
  2. Design Tokens Dynamiques : Permettre un passage fluide entre des thèmes (Light/Dark) non seulement sur les couleurs, mais sur des espacements, des arrondis ou des intensités d'ombres.
  3. Performances et Contrôle : Éviter le recours excessif au JavaScript pour manipuler le DOM lors d'animations complexes, en déléguant le calcul d'interpolation au moteur CSS (souvent optimisé via le GPU).

3. Comment

A. Syntaxe de base

Pour rendre une variable animable, on doit la déclarer dans le scope global (souvent dans :root ou un fichier de variables) en utilisant @property.

@property --my-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
  • syntax : Définit le type de donnée. C'est ce qui active l'interpolation.
  • initial-value : Valeur de secours obligatoire si la variable n'est pas définie.
  • inherits : Booléen indiquant si la valeur est héritée par les enfants.

B. Cas concret : Animation d'un Gradient Rotatif

Voici une implémentation robuste pour créer un bouton avec un bord animé et un gradient fluide, technique très utilisée dans les interfaces "Premium/Futuriste".

/* 1. Définition des propriétés typées pour l'interpolation */
@property --gradient-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}

@property --main-color {
syntax: '<color>';
initial-value: #3498db;
inherits: false;
}

:root {
--animation-speed: 3s;
}

.animated-card {
width: 300px;
height: 200px;
border-radius: 20px;
position: relative;
background: #1a1a1a;
display: grid;
place-items: center;
color: white;
font-family: sans-serif;
z-index: 1;
}

/* Le pseudo-élément crée l'effet de bordure animée */
.animated-card::before {
content: '';
position: absolute;
inset: -4px; /* Bordure de 4px */
z-index: -1;
border-radius: 24px;

/* Utilisation des variables typées */
background: conic-gradient(
from var(--gradient-angle),
var(--main-color),
#e74c3c,
var(--main-color)
);

/* Animation fluide grâce à l'interpolation @property */
animation: rotate-gradient var(--animation-speed) linear infinite;
}

@keyframes rotate-gradient {
to {
--gradient-angle: 360deg;
--main-color: #9b59b6; /* La couleur change aussi fluidement */
}
}

C. Limitations

  1. Support Navigateur : Bien que largement supporté par Chromium (Chrome, Edge, Opera), Safari et Firefox ont mis plus de temps à implémenter @property. Pour une production critique, un fallback (comme une animation de transform: rotate() sur un élément plus large que le container) est recommandé.
  2. Types Limités : On ne peut interpoler que des types reconnus par le standard CSS (<color>, <length>, <percentage>, <angle>, <number>, <integer>). On ne peut pas interpoler des chaînes de caractères arbitraires.
  3. Coût CPU/GPU : L'interpolation fréquente de variables utilisées dans des calculs complexes (comme calc()) peut impacter les performances sur des appareils mobiles très anciens.

4. Zone de Danger

L'erreur classique : Animer sans @property

.box {
--my-angle: 0deg;
transition: --my-angle 0.5s;
}
.box:hover {
--my-angle: 180deg;
}
/* Résultat : La valeur saute instantanément de 0 à 180 sans transition. */

La bonne pratique : Typer la variable

@property --my-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
.box {
--my-angle: 0deg;
transition: --my-angle 0.5s ease-in-out;
}
.box:hover {
--my-angle: 180deg;
}
/* Résultat : Le navigateur calcule chaque degré entre 0 et 180. */

Mécanisme d'interpolation des variables CSS

Questions clés

1. Pourquoi une variable CSS standard ne peut-elle pas être animée fluidement ?

Découvrir la réponse

Parce que le navigateur traite les variables CSS comme des chaînes de caractères. Sans information sur le type de donnée (nombre, angle, couleur), le moteur de rendu ne peut pas effectuer de calcul d'interpolation linéaire entre deux valeurs ; il se contente de remplacer la valeur A par la valeur B instantanément.

2. Quelle est la différence entre inherits: true et inherits: false dans @property ?

Découvrir la réponse

inherits: true signifie que si vous définissez la variable sur un élément parent, tous les éléments enfants hériteront de cette valeur, comme une propriété CSS standard (ex: color). inherits: false limite la portée de la variable, évitant ainsi des recalculs de style inutiles dans l'arbre DOM et améliorant potentiellement les performances.

3. Peut-on utiliser @property pour animer un linear-gradient directement ?

Découvrir la réponse

Non. Un gradient est considéré comme une image (image type). On ne peut pas interpoler deux images. Cependant, on peut animer les composants du gradient (couleurs, positions, angles) en les isolant dans des variables typées avec @property.

4. Quel est l'impact de l'oubli de initial-value dans une déclaration @property ?

Découvrir la réponse

La déclaration @property sera considérée comme invalide par le navigateur. L' initial-value est obligatoire car elle sert de point de référence pour le moteur de rendu si aucune valeur n'est spécifiée dans le CSS, garantissant que l'interpolation a toujours un point de départ valide.

Mise en pratique

Exercice 1 : Reproduction guidée

Objectif : Créer un cercle dont la couleur de fond et la taille d'un rayon d'ombre (box-shadow) s'animent fluidement au survol.

  • Déclarez deux propriétés : --bg-color (<color>) et --shadow-size (<length>).
  • Créez un élément .circle de 100px.
  • Appliquez une transition de 0.3s sur ces deux variables.
  • Au survol, changez la couleur et augmentez la taille de l'ombre.
Découvrir la solution commentée
/* Définition des types pour permettre l'interpolation */
@property --bg-color {
syntax: '<color>';
initial-value: #3498db;
inherits: false;
}

@property --shadow-size {
syntax: '<length>';
initial-value: 0px;
inherits: false;
}

.circle {
width: 100px;
height: 100px;
border-radius: 50%;

/* Utilisation des variables */
background-color: var(--bg-color);
box-shadow: 0 0 var(--shadow-size) var(--bg-color);

/* On anime les variables, pas les propriétés finales */
transition: --bg-color 0.3s ease, --shadow-size 0.3s ease;
cursor: pointer;
}

.circle:hover {
--bg-color: #e74c3c;
--shadow-size: 20px;
}

Exercice 2 : Adaptation

Objectif : Transformer l'animation de gradient rotatif vue dans le cours pour qu'elle ne s'active que lors du survol d'un container, avec un effet de "ralentissement" (easing) au début et à la fin.

  • Utilisez @property pour l'angle.
  • L'animation doit être une transition et non une animation infinie.
  • L'angle doit passer de 0deg à 360deg lors du hover.
Découvrir la solution commentée
@property --gradient-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}

.container {
width: 200px;
height: 200px;
border-radius: 15px;
position: relative;
background: #222;
z-index: 1;
}

.container::before {
content: '';
position: absolute;
inset: -5px;
z-index: -1;
border-radius: 20px;
background: conic-gradient(from var(--gradient-angle), #ff00cc, #3333ff, #ff00cc);

/* Transition fluide sur la variable typée */
transition: --gradient-angle 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.container:hover::before {
--gradient-angle: 360deg;
}

Exercice 3 : Conception

Objectif : Créer un "Indicateur de Chargement" (Loader) sophistiqué. Le loader doit être un anneau dont la couleur change dynamiquement (interpolation de couleur) et dont l'épaisseur de la bordure varie (interpolation de longueur) tout en tournant.

  • Contrainte : Vous devez utiliser au moins 3 variables typées avec @property.
  • L'animation doit être fluide et infinie.
  • Le rendu doit être professionnel.
Comment l'anneau est construit

La technique utilisée dans la solution repose sur une bordure CSS ordinaire dont trois côtés sont transparents. La variable --loader-angle pilote la rotation de l'élément via transform: rotate(), la variable --loader-color change la couleur du côté visible, et --loader-width change l'épaisseur. Les trois variables étant typées via @property, elles sont toutes interpolées mathématiquement, donnant une animation parfaitement fluide.

Découvrir la solution commentée
<!-- Structure HTML nécessaire -->
<div class="loader-demo">
<div class="loader"></div>
</div>
/* 1. Déclaration des types pour activer l'interpolation */
@property --loader-color {
syntax: '<color>';
initial-value: #7c3aed; /* Violet — visible sur fond clair et sombre */
inherits: false;
}

@property --loader-width {
syntax: '<length>';
initial-value: 4px;
inherits: false;
}

@property --loader-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}

/* 2. Conteneur de démo avec fond neutre pour la visibilité */
.loader-demo {
display: flex;
align-items: center;
justify-content: center;
padding: 3rem;
background: #f8f9fa;
border-radius: 12px;
}

/* 3. Le loader lui-même */
.loader {
width: 60px;
height: 60px;
border-radius: 50%;

/*
Technique de l'anneau par bordure partielle :
- border-top : côté visible avec la couleur animée
- border-right, bottom, left : transparents → ne montrent qu'un arc
L'épaisseur (--loader-width) interpole de 4px à 8px fluidement.
*/
border-top: var(--loader-width) solid var(--loader-color);
border-right: var(--loader-width) solid transparent;
border-bottom: var(--loader-width) solid transparent;
border-left: var(--loader-width) solid transparent;

/*
La rotation est pilotée par --loader-angle.
Grâce à @property syntax: '<angle>', le navigateur
interpole chaque degré de 0 à 360, produisant une
rotation parfaitement fluide.
*/
transform: rotate(var(--loader-angle));

animation: complex-load 2s linear infinite;
}

/* 4. Keyframes faisant évoluer les 3 variables simultanément */
@keyframes complex-load {
0% {
--loader-angle: 0deg;
--loader-color: #7c3aed; /* Violet */
--loader-width: 4px;
}
33% {
--loader-color: #3b82f6; /* Bleu */
}
50% {
--loader-width: 8px; /* L'anneau s'épaissit au milieu */
}
66% {
--loader-color: #06b6d4; /* Cyan */
}
100% {
--loader-angle: 360deg;
--loader-color: #7c3aed; /* Retour au Violet */
--loader-width: 4px;
}
}

Ce que vous devriez observer :

  • Une rotation fluide en continu (pilotée par --loader-angle).
  • Une transition de couleur progressive : violet → bleu → cyan → violet (pilotée par --loader-color).
  • Une variation d'épaisseur de l'arc au milieu de l'animation : 4px → 8px → 4px (pilotée par --loader-width).