# CSS @property: verlopen en custom properties animeren

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

Verlopen weigeren over te gaan omdat de browser de ene afbeelding niet in de andere kan mengen. Geef een custom property een type en die grens verdwijnt. Zo werkt @property, met code om te plakken.

## The short version

- CSS @property registreert een custom property met een syntax, een overervingsregel en een beginwaarde, waarmee de browser weet welk type waarde hij bevat.
- Browsers kunnen een verloop niet rechtstreeks laten overgaan, omdat background-image niet interpoleerbaar is, maar ze kunnen wel een getypeerde custom property laten overgaan die in het verloop wordt gebruikt.
- Getypeerde properties zoals <color>, <angle>, <percentage> en <length> animeren soepel; een property met de universele *-syntax wisselt alleen tussen waarden.
- De @property-regel wordt ondersteund in huidige Chrome, Edge, Safari en Firefox, en browsers die hem negeren tonen het verloop gewoon zonder beweging.
- Een custom property in een achtergrond animeren tekent het element bij elk frame opnieuw, dus houd het geanimeerde gebied bescheiden en respecteer prefers-reduced-motion.

**CSS @property** registreert een custom property met een type, zodat de browser weet dat `--angle` een hoek bevat of `--tint` een kleur. Zodra hij het type kent, kan hij tussen twee waarden interpoleren, wat betekent dat je dingen kunt laten overgaan en animeren die CSS normaal weigert te bewegen: verloopkleuren, verloophoeken en de positie van een kleurstop. Zonder registratie is een custom property gewoon een string, en een string kan alleen van de ene waarde naar de volgende springen.

## Waarom verlopen niet uit zichzelf overgaan

Probeer `transition: background 0.4s` op een knop waarvan de hoverstaat het ene `linear-gradient()` voor het andere verwisselt, en niets vloeit: het nieuwe verloop springt erin. Verlopen zijn afbeeldingen, en de specificatie behandelt `background-image` als niet interpoleerbaar, dus de browser kan de ene afbeelding niet in een andere mengen.

De gebruikelijke omweg is de achtergrond te groot maken en `background-position` te verschuiven, zoals de meeste [geanimeerde CSS-verlopen](https://gradiently.design/nl/guide/css-animated-gradient) zijn gebouwd. Het werkt, maar het verplaatst alleen een vast verloop. Je kunt geen kleur veranderen, geen hoek draaien of een stop verschuiven. Geregistreerde properties veranderen dat, omdat wat wordt geanimeerd niet langer de afbeelding is maar een getypeerd getal of een kleur erin. De browser berekent het verloop bij elk frame opnieuw uit de huidige waarde.

### Niet-geregistreerde --tint

- Opgeslagen als een reeks tokens
- Overgangen springen halverwege
- Erft standaard
- Een ongeldige waarde breekt de declaratie op berekeningsmoment

### Geregistreerd met @property

- Geparsed als een echte kleur
- Overgangen interpoleren soepel
- Overerving is jouw keuze
- Een ongeldige waarde valt terug op de beginwaarde

## De @property-syntax

Een `@property`-regel heeft drie descriptors. `syntax` zegt welk type waarde is toegestaan, `inherits` zegt of kinderen de waarde ontvangen en `initial-value` wordt gebruikt als niets anders hem instelt. Alle drie zijn verplicht, behalve dat `initial-value` mag ontbreken als de syntax `*` is. Ontbreekt of klopt een verplicht onderdeel niet, dan negeert de browser de hele regel, zonder melding.

```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%;
}
```

Drie geregistreerde properties: een kleur, een hoek en een stoppositie. Registreer ze één keer, op het hoogste niveau van een stylesheet.

De beginwaarde moet rekenkundig onafhankelijk zijn, wat in de praktijk absolute eenheden betekent: `0deg`, `40%`, `12px` en hexkleuren zijn goed, terwijl `2em` of `var(--x)` dat niet zijn. `inherits: false` instellen is meestal wat je wilt voor animatie, en het bespaart de browser het naar beneden duwen van de waarde door de boom.

| Syntax | Animeert soepel | Goed voor |
| --- | --- | --- |
| `<color>` | Ja | Verloopkleuren, themawissels |
| `<angle>` | Ja | Lineaire hoeken, conische rotatie |
| `<percentage>` | Ja | Posities van kleurstops, groottes |
| `<length>` | Ja | Radiale groottes, verschuivingen |
| `<number>` | Ja | Waarden zoals dekking, vermenigvuldigers |
| `<integer>` | Ja, in hele stappen | Tellers, gestapte effecten |
| `*` | Nee, hij wisselt | Alles wat je nooit animeert |

De syntaxen die ertoe doen voor verloopwerk. Je kunt er ook meerdere accepteren, zoals `'<length> | <percentage>'`, of een lijst met `+`.

## Een verloopkleur animeren bij hover

Dit is het kleinste nuttige voorbeeld. De knop gebruikt `--tint` als tweede kleur en de hoverstaat verandert alleen `--tint`. Omdat de property als kleur is geregistreerd, vloeit de overgang tussen violet en koraal in plaats van te springen.

```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;
}
```

De transition noemt de custom property zelf. Transition: background schrijven zou hier niets doen.

- In rust: --tint is violet: `linear-gradient(120deg, #1e1b4b 0%, #7c3aed 100%)`
- Halverwege de overgang: `linear-gradient(120deg, #1e1b4b 0%, #bb56b9 100%)`
- Bij hover: --tint is koraal: `linear-gradient(120deg, #1e1b4b 0%, #fb7185 100%)`

Drie frames van dezelfde knop. De middelste kleur bestaat alleen omdat de browser een geregistreerde kleur kan interpoleren.

Voor meer manieren om knoppen te behandelen, zie [verloopknop-CSS](https://gradiently.design/nl/guide/css-gradient-button) en [CSS-verloop hover-effecten](https://gradiently.design/nl/guide/css-hover-gradient).

## Een conische verlooprand laten draaien

Een favoriet gebruik van `@property` is een rand die rond een kaart lijkt te reizen. Een [conisch verloop](https://gradiently.design/nl/guide/css-conic-gradient) begint vanaf een hoek, dus die hoek registreren en van `0deg` naar `360deg` animeren laat de kleuren draaien. Twee achtergronden doen het werk: de kaartkleur bijgesneden op de padding-box en het conische verloop bijgesneden op de 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; }
}
```

Herhaal de eerste kleur aan het eind zodat de naad waar 360deg 0deg ontmoet verdwijnt.

De conische ring op 0deg: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

Hetzelfde verloop dat de rand gebruikt. Naarmate --angle groeit, draait deze ring, en de dunne strook die je rond de kaart ziet reist mee. [Verloopranden in CSS](https://gradiently.design/nl/guide/css-gradient-border) behandelt de statische versie.

## Een kleurstop verplaatsen

Met een geregistreerd percentage kan een stop schuiven. Gebruik het voor een voortgangsvulling, een highlight die over een kop veegt of een horizon die stijgt bij scrollen. Hier verplaatst `--stop` het punt waar het verloop van inkt naar groenblauw gaat.

```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%;
}
```

Twee stops op dezelfde positie maken een harde rand, en de rand beweegt als --stop verandert.

## Registreren vanuit JavaScript

`CSS.registerProperty()` doet hetzelfde vanuit een script. Het is handig als een designsysteem zijn properties tijdens runtime registreert, of als een waarde pas na het laden bekend wordt. Dezelfde naam twee keer registreren geeft een fout, dus bescherm het.

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

De JavaScript-vorm gebruikt initialValue in camelCase. Al het andere komt overeen met de CSS-regel.

## Browserondersteuning, terugvallen en prestaties

`@property` werkt in huidige Chrome, Edge, Safari en Firefox; Firefox voegde het als laatste toe, in versie 128. Controleer [caniuse](https://caniuse.com/mdn-css_at-rules_property) als je oudere apparaten ondersteunt. Een browser die de regel niet begrijpt behandelt `--angle` als een gewone custom property, dus je verloop wordt nog steeds getekend op zijn beginwaarde en beweegt gewoon niet. Dat is een prima terugval, mits het stilstaande beeld af oogt.

> **Let op het hertekenen** Een property animeren die in `background` wordt gebruikt laat de browser dat element bij elk frame opnieuw tekenen. Een kleine rand of knop is goedkoop; een hero op volledig scherm die eindeloos animeert kost batterij. [CSS-verloopprestaties](https://gradiently.design/nl/guide/css-gradient-performance) heeft de metingen om in de gaten te houden.

1. **Registreer vóór gebruik** Zet elke `@property`-regel op het hoogste niveau, buiten mediaquery’s, zodat hij overal geldt.
2. **Gebruik getypeerde syntaxen** Kies `<color>`, `<angle>` of `<percentage>`. Vermijd `*` voor alles wat je wilt animeren.
3. **Laat de property overgaan** Schrijf `transition: --tint 400ms`, met de custom property erin in plaats van `background`.
4. **Respecteer verminderde beweging** Stop herhalende animaties onder `prefers-reduced-motion: reduce`, zoals beschreven in [prefers reduced motion](https://gradiently.design/nl/guide/reduced-motion).
5. **Controleer het stilstaande beeld** Zet de animatie uit en zorg dat het verloop in rust er nog steeds bedoeld uitziet.

Leeft de beweging die je wilt op socialposts of video in plaats van een webpagina, dan draagt een Gradiently Mark al zijn eigen licht en trage beweging, en Pro exporteert het als MP4, WebM of GIF waar de browser opnemen ondersteunt, zonder keyframes te schrijven. Voor alles op het web is `@property` het zuiverste gereedschap dat je hebt. De [MDN-referentie](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) noemt elke descriptor.

## FAQ

### Wat doet CSS @property?

Het registreert een custom property met een type, een overervingsregel en een beginwaarde. Door het type te kennen kan de browser de waarde valideren en interpoleren in overgangen en animaties.

### Kun je een CSS-verloop animeren?

Niet rechtstreeks, omdat background-image niet interpoleerbaar is. Registreer de kleuren, hoek of stopposities met @property, gebruik ze in het verloop en animeer die properties.

### Waarom werkt mijn @property-animatie niet?

Meestal ontbreekt een descriptor, gebruikt de beginwaarde een relatieve eenheid, is de syntax `*`, of noemt de transition `background` in plaats van de custom property. Elke ongeldige descriptor laat de browser de hele regel negeren.

### Ondersteunt Firefox @property?

Ja. Firefox voegde @property toe in versie 128, dus het werkt nu in elke grote huidige browser.

### Moet inherits true of false zijn?

Gebruik false voor de meeste geanimeerde waarden. Het houdt de waarde op het element waar je hem instelt en bespaart de browser extra werk.
