# @property en CSS : animer dégradés et propriétés personnalisées

[Canonical HTML page](https://gradiently.design/fr/guide/css-property-animation)

Les dégradés refusent les transitions car le navigateur ne sait pas fondre une image dans une autre. Donnez un type à une propriété personnalisée et cette limite disparaît. Voici comment fonctionne @property, avec du code à coller.

## The short version

- @property en CSS déclare une propriété personnalisée avec une syntaxe, une règle d’héritage et une valeur initiale, ce qui indique au navigateur quel type de valeur elle contient.
- Les navigateurs ne peuvent pas animer directement un dégradé, car background-image n’est pas interpolable, mais ils peuvent animer une propriété personnalisée typée utilisée dans le dégradé.
- Les propriétés typées comme <color>, <angle>, <percentage> et <length> s’animent en douceur ; une propriété à la syntaxe universelle * ne fait que sauter d’une valeur à l’autre.
- La règle @property est prise en charge dans les versions actuelles de Chrome, Edge, Safari et Firefox, et les navigateurs qui l’ignorent affichent simplement le dégradé sans mouvement.
- Animer une propriété personnalisée dans un arrière-plan redessine l’élément à chaque image : gardez la zone animée modeste et respectez prefers-reduced-motion.

**@property en CSS** déclare une propriété personnalisée avec un type, pour que le navigateur sache que `--angle` contient un angle ou que `--tint` contient une couleur. Une fois le type connu, il peut interpoler entre deux valeurs : vous pouvez donc animer ce que le CSS refuse normalement de bouger, comme les couleurs d’un dégradé, son angle ou la position d’un arrêt de couleur. Sans déclaration, une propriété personnalisée n’est qu’une chaîne, et une chaîne ne peut que sauter d’une valeur à la suivante.

## Pourquoi les dégradés ne s’animent pas seuls

Essayez `transition: background 0.4s` sur un bouton dont l’état de survol remplace un `linear-gradient()` par un autre : rien ne s’adoucit, le nouveau dégradé apparaît d’un coup. Les dégradés sont des images, et la spécification considère `background-image` comme non interpolable : le navigateur n’a aucun moyen de fondre une image dans une autre.

Le contournement habituel consiste à surdimensionner l’arrière-plan et à faire glisser `background-position`, et c’est ainsi que sont construits la plupart des [dégradés CSS animés](https://gradiently.design/fr/guide/css-animated-gradient). Ça marche, mais cela ne fait que déplacer un dégradé figé. Impossible de changer une couleur, de faire tourner un angle ou de pousser un arrêt. Les propriétés déclarées changent la donne, car ce qui est animé n’est plus l’image mais un nombre ou une couleur typés à l’intérieur. Le navigateur recalcule le dégradé à chaque image à partir de la valeur courante.

### --tint non déclarée

- Stockée comme une suite de jetons
- Les transitions sautent à mi-parcours
- Héritée par défaut
- Une valeur invalide casse la déclaration au calcul

### Déclarée avec @property

- Analysée comme une vraie couleur
- Les transitions s’interpolent en douceur
- L’héritage est à votre choix
- Une valeur invalide revient à la valeur initiale

## La syntaxe de @property

Une règle `@property` a trois descripteurs. `syntax` indique quel type de valeur est autorisé, `inherits` si les enfants reçoivent la valeur, et `initial-value` est utilisée quand rien d’autre ne la définit. Les trois sont obligatoires, sauf `initial-value` qui peut être omise quand la syntaxe est `*`. Si une partie obligatoire manque ou est erronée, le navigateur ignore toute la règle, sans rien dire.

```css
@property --tint {
  syntax: '<color>';
  inherits: false;
  initial-value: #7c3aed;
}

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

@property --stop {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 40%;
}
```

Trois propriétés déclarées : une couleur, un angle et une position d’arrêt. Déclarez-les une fois, au premier niveau d’une feuille de style.

La valeur initiale doit être indépendante du calcul, ce qui signifie en pratique des unités absolues : `0deg`, `40%`, `12px` et les couleurs hexadécimales conviennent, `2em` ou `var(--x)` non. Définir `inherits: false` est en général ce qu’il faut pour l’animation, et évite au navigateur de propager la valeur dans l’arbre.

| Syntaxe | S’anime en douceur | Utile pour |
| --- | --- | --- |
| `<color>` | Oui | Couleurs de dégradé, changements de thème |
| `<angle>` | Oui | Angles linéaires, rotation conique |
| `<percentage>` | Oui | Positions d’arrêt, tailles |
| `<length>` | Oui | Tailles radiales, décalages |
| `<number>` | Oui | Valeurs de type opacité, multiplicateurs |
| `<integer>` | Oui, par paliers entiers | Compteurs, effets par paliers |
| `*` | Non, elle saute | Tout ce que vous n’animez jamais |

Les syntaxes qui comptent pour les dégradés. Vous pouvez aussi en accepter plusieurs, comme `'<length> | <percentage>'`, ou une liste avec `+`.

## Animer une couleur de dégradé au survol

Voici le plus petit exemple utile. Le bouton utilise `--tint` comme seconde couleur, et l’état de survol ne change que `--tint`. Comme la propriété est déclarée en tant que couleur, la transition passe en douceur du violet au corail au lieu de sauter.

```css
@property --tint {
  syntax: '<color>';
  inherits: false;
  initial-value: #7c3aed;
}

.button {
  background: linear-gradient(120deg, #1e1b4b 0%, var(--tint) 100%);
  transition: --tint 400ms ease;
}

.button:hover {
  --tint: #fb7185;
}
```

La transition nomme la propriété personnalisée elle-même. Écrire transition: background ne ferait rien ici.

- Au repos : --tint est violet: `linear-gradient(120deg, #1e1b4b 0%, #7c3aed 100%)`
- À mi-parcours de la transition: `linear-gradient(120deg, #1e1b4b 0%, #bb56b9 100%)`
- Survol : --tint est corail: `linear-gradient(120deg, #1e1b4b 0%, #fb7185 100%)`

Trois images du même bouton. La couleur intermédiaire n’existe que parce que le navigateur sait interpoler une couleur déclarée.

Pour d’autres traitements de boutons, voyez [les boutons en dégradé CSS](https://gradiently.design/fr/guide/css-gradient-button) et [les effets de dégradé au survol en CSS](https://gradiently.design/fr/guide/css-hover-gradient).

## Faire tourner une bordure en dégradé conique

Un usage favori de `@property` est une bordure qui semble faire le tour d’une carte. Un [dégradé conique](https://gradiently.design/fr/guide/css-conic-gradient) part d’un angle : déclarer cet angle et l’animer de `0deg` à `360deg` fait tourner les couleurs. Deux arrière-plans font le travail : la couleur de la carte découpée à la padding box, et le dégradé conique découpé à la border box.

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

.card {
  border: 2px solid transparent;
  border-radius: 16px;
  background:
    linear-gradient(#0f0b1e, #0f0b1e) padding-box,
    conic-gradient(from var(--angle), #22d3ee, #7c3aed, #f472b6, #22d3ee) border-box;
  animation: spin 6s linear infinite;
}

@keyframes spin {
  to { --angle: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
  .card { animation: none; }
}
```

Répétez la première couleur à la fin pour faire disparaître la jointure où 360deg rejoint 0deg.

L’anneau conique à 0deg: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

Le même dégradé que celui de la bordure. Quand --angle augmente, cet anneau tourne, et la fine bande visible autour de la carte voyage avec lui. [Les bordures en dégradé CSS](https://gradiently.design/fr/guide/css-gradient-border) traite la version statique.

## Déplacer un arrêt de couleur

Un pourcentage déclaré permet à un arrêt de glisser. Utilisez-le pour un remplissage de progression, une mise en valeur qui balaie un titre ou un horizon qui monte au défilement. Ici, `--stop` déplace le point où le dégradé passe de l’encre au bleu canard.

```css
@property --stop {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 20%;
}

.meter {
  background: linear-gradient(90deg, #0d9488 0%, #0d9488 var(--stop), #0f172a var(--stop));
  transition: --stop 600ms ease-out;
}

.meter[data-done] {
  --stop: 100%;
}
```

Deux arrêts à la même position créent un bord net, et ce bord se déplace quand --stop change.

## Déclarer depuis JavaScript

`CSS.registerProperty()` fait le même travail depuis un script. C’est pratique quand un design system déclare ses propriétés à l’exécution, ou quand une valeur n’est connue qu’après le chargement. Déclarer deux fois le même nom lève une erreur : protégez l’appel.

```js
if ('registerProperty' in CSS) {
  try {
    CSS.registerProperty({
      name: '--angle',
      syntax: '<angle>',
      inherits: false,
      initialValue: '0deg',
    })
  } catch {
    // Already registered, which is fine.
  }
}
```

La forme JavaScript écrit initialValue en camelCase. Tout le reste correspond à la règle CSS.

## Prise en charge, replis et performances

`@property` fonctionne dans les versions actuelles de Chrome, Edge, Safari et Firefox ; Firefox a été le dernier à l’ajouter, en version 128. Consultez [caniuse](https://caniuse.com/mdn-css_at-rules_property) si vous prenez en charge des appareils plus anciens. Un navigateur qui ne comprend pas la règle traite `--angle` comme une propriété personnalisée ordinaire : votre dégradé s’affiche toujours à sa valeur de départ et ne bouge simplement pas. C’est un bon repli, à condition que l’image fixe paraisse aboutie.

> **Attention au rendu** Animer une propriété utilisée dans `background` oblige le navigateur à redessiner cet élément à chaque image. Une petite bordure ou un bouton coûte peu ; un en-tête plein écran animé en continu consomme de la batterie. [Les performances des dégradés CSS](https://gradiently.design/fr/guide/css-gradient-performance) donne les mesures à surveiller.

1. **Déclarez avant d’utiliser** Placez chaque règle `@property` au premier niveau, hors des media queries, pour qu’elle s’applique partout.
2. **Utilisez des syntaxes typées** Choisissez `<color>`, `<angle>` ou `<percentage>`. Évitez `*` pour tout ce que vous comptez animer.
3. **Faites la transition sur la propriété** Écrivez `transition: --tint 400ms`, en nommant la propriété personnalisée plutôt que `background`.
4. **Respectez le mouvement réduit** Arrêtez les animations en boucle sous `prefers-reduced-motion: reduce`, comme le décrit [prefers-reduced-motion](https://gradiently.design/fr/guide/reduced-motion).
5. **Vérifiez l’image fixe** Désactivez l’animation et assurez-vous que le dégradé au repos paraît toujours voulu.

Si le mouvement que vous voulez vit sur des publications sociales ou en vidéo plutôt que sur une page web, un Mark Gradiently porte déjà sa propre lumière et son mouvement lent, et Pro l’exporte en MP4, WebM ou GIF là où le navigateur prend en charge l’enregistrement, sans écrire d’images clés. Pour tout ce qui se passe sur le web, `@property` est l’outil le plus propre dont vous disposez. La [référence MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) liste tous les descripteurs.

## FAQ

### À quoi sert @property en CSS ?

Elle déclare une propriété personnalisée avec un type, une règle d’héritage et une valeur initiale. Connaître le type permet au navigateur de valider la valeur et de l’interpoler dans les transitions et les animations.

### Peut-on animer un dégradé CSS ?

Pas directement, car background-image n’est pas interpolable. Déclarez les couleurs, l’angle ou les positions d’arrêt avec @property, utilisez-les dans le dégradé et animez plutôt ces propriétés.

### Pourquoi mon animation @property ne fonctionne-t-elle pas ?

En général, un descripteur manque, la valeur initiale utilise une unité relative, la syntaxe est `*`, ou la transition nomme `background` au lieu de la propriété personnalisée. Tout descripteur invalide fait ignorer la règle entière.

### Firefox prend-il en charge @property ?

Oui. Firefox a ajouté @property en version 128 : la règle fonctionne donc dans tous les grands navigateurs actuels.

### inherits doit-il valoir true ou false ?

false pour la plupart des valeurs animées. La valeur reste ainsi sur l’élément où vous la définissez et le navigateur évite un travail supplémentaire.
