# Geanimeerde CSS-kleurverloopachtergronden, goed gedaan

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

Kleurverlopen zijn niet direct te animeren, maar alles eromheen wel. Vier technieken, wat elk de browser kost en hoe je beweging rustig en optioneel houdt.

## The short version

- Browsers kunnen niet interpoleren tussen twee kleurverloopwaarden, dus een geanimeerd CSS-kleurverloop verplaatst, vervaagt of transformeert het kleurverloop in plaats van het direct te animeren.
- De klassieke techniek maakt de achtergrond groter dan het element en animeert background-position, wat overal werkt maar elk beeld opnieuw tekent.
- Aangepaste eigenschappen registreren met @property laat de browser afzonderlijke kleuren, hoeken en posities binnen een kleurverloop animeren.
- Transform of opacity animeren op een aparte kleurverloopblaag is meestal de goedkoopste optie, omdat browsers die vaak kunnen samenstellen zonder opnieuw te tekenen.
- Elke kleurverloopanimatie moet stoppen, of bijna stilstaan, als de gebruiker om verminderde beweging heeft gevraagd.

Een **geanimeerd CSS-kleurverloop** is een kleurverloopachtergrond die in de tijd van kleur of positie verschuift. Er is een addertje: schrijf je twee verschillende kleurverlopen in een `@keyframes`-regel, dan mengen browsers ze niet, ze springen. Elke werkende techniek animeert daarom iets naast het kleurverloop: zijn positie, de aangepaste eigenschappen erin of de laag waarop het is getekend. Welke je kiest bepaalt hoe vloeiend het eruitziet en hoeveel werk de browser per beeld doet.

- Beeld 1: schemering: `linear-gradient(120deg, #1e1b4b, #7c3aed 45%, #f472b6)`
- Beeld 2: later: `linear-gradient(160deg, #1e1b4b, #6d28d9 35%, #fb7185)`
- Beeld 3: sintel: `linear-gradient(200deg, #1e1b4b, #4c1d95 30%, #fb923c)`

Drie momenten van één trage animatie. Richting en kleur bewegen allebei, maar het palet blijft één familie.

Voor de ontwerpkant, wanneer beweging een merk helpt en hoe je haar tempo bepaalt, zie [geanimeerde kleurverloopachtergronden](https://gradiently.design/nl/guide/animated-gradient-background). Deze gids is de code.

## Techniek 1: verplaats een te grote achtergrond

Maak het kleurverloop twee tot vier keer zo groot als het element met `background-size` en animeer dan `background-position`, zodat na verloop van tijd een ander deel zichtbaar is. Het werkt in elke browser en heeft geen JavaScript nodig. Gebruik `alternate` zodat de beweging soepel omkeert in plaats van terug te springen naar het begin.

```css
.hero {
  background-color: #1e1b4b;
  background-image: linear-gradient(120deg, #1e1b4b, #7c3aed, #f472b6, #fb923c);
  background-size: 300% 300%;
  animation: pan 18s ease-in-out infinite alternate;
}

@keyframes pan {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}
```

Het klassieke geanimeerde kleurverloop. Trage duren van 12 tot 30 seconden voelen als sfeer, niet als drukte.

De kosten: `background-position` is niet iets wat browsers alleen op de videokaart kunnen verplaatsen, dus het element wordt elk beeld opnieuw getekend. Op een knop is dat niets. Op een hero over het hele scherm is het echt werk dat blijft draaien zolang de pagina open is.

## Techniek 2: animeer kleurstops met @property

Aangepaste eigenschappen zijn normaal strings, en die kunnen niet worden geïnterpoleerd. Registreer je er een met `@property`, dan krijgt hij een type, zoals `<color>`, `<angle>` of `<percentage>`, en getypeerde eigenschappen animeren vloeiend. Gebruik ze in het kleurverloop en je kunt de kleuren, de hoek of de positie van een stop direct animeren. `@property` wordt door alle huidige grote browsers ondersteund; kijk op [caniuse](https://caniuse.com/mdn-css_at-rules_property) als je oudere ondersteunt.

```css
@property --from {
  syntax: "<color>";
  inherits: false;
  initial-value: #7c3aed;
}
@property --to {
  syntax: "<color>";
  inherits: false;
  initial-value: #f472b6;
}
@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 120deg;
}

.hero {
  background: linear-gradient(var(--angle), var(--from), var(--to));
  animation: shift 16s ease-in-out infinite alternate;
}

@keyframes shift {
  to {
    --from: #0891b2;
    --to: #fb923c;
    --angle: 200deg;
  }
}
```

Kleuren en hoek die binnen het kleurverloop animeren. Niet-geregistreerde eigenschappen zouden springen in plaats van mengen.

- Begin: violet naar roze: `linear-gradient(120deg, #7c3aed, #f472b6)`
- Eind: cyaan naar oranje: `linear-gradient(200deg, #0891b2, #fb923c)`

De twee uiteinden van de animatie hierboven. De browser mengt elk beeld ertussen.

Ook deze techniek tekent elk beeld opnieuw, net als de eerste. Het voordeel is controle: je kunt één gloed in een [mesh gradient](https://gradiently.design/nl/guide/css-mesh-gradient) verplaatsen, een [conische rand](https://gradiently.design/nl/guide/css-gradient-border) draaien of een merkkleurverloop richting een tweede palet laten verschuiven zonder een te grote achtergrond.

## Techniek 3: transformeer een kleurverloopblaag

Zet het kleurverloop op een pseudo-element dat veel groter is dan het element en animeer zijn `transform`, bijvoorbeeld een trage rotatie of drift. Browsers kunnen een getransformeerde laag meestal op de videokaart verplaatsen zonder hem opnieuw te tekenen, dus dit is de goedkoopste manier om een groot kleurverloop te animeren. `will-change: transform` geeft aan dat de laag vooraf gepromoveerd moet worden.

```css
.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.hero::before {
  content: "";
  position: absolute;
  inset: -50%;
  z-index: -1;
  background: conic-gradient(from 0deg, #1e1b4b, #7c3aed, #f472b6, #0891b2, #1e1b4b);
  animation: turn 40s linear infinite;
  will-change: transform;
}

@keyframes turn {
  to { transform: rotate(1turn); }
}
```

Een enorme conic gradient die langzaam draait achter de inhoud. De negatieve inset houdt de hoeken bedekt terwijl hij draait.

## Techniek 4: crossfade twee kleurverlopen

Stapel twee kleurverloopblagen en animeer de `opacity` van de bovenste. Opacity is ook een eigenschap die de compositor aankan, dus de overgang is vloeiend en goedkoop. Het past bij trage stemmingswisselingen, zoals een dagpalet dat overgaat in een nachtpalet, en de twee kleurverlopen mogen in structuur volledig verschillen.

```css
.sky {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, #7dd3fc, #fde68a);
}

.sky::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, #0f172a, #7c3aed);
  animation: dusk 20s ease-in-out infinite alternate;
}

@keyframes dusk {
  from { opacity: 0; }
  to   { opacity: 1; }
}
```

Dag gaat over in nacht en terug. Alleen opacity verandert, dus er wordt niets opnieuw getekend.

## Een techniek kiezen

| Techniek | Werk van de browser per beeld | Het best voor |
| --- | --- | --- |
| `background-position` verplaatsen | Opnieuw tekenen | Kleine elementen, knoppen, tekst |
| `@property`-kleuren en -hoeken | Opnieuw tekenen | Precieze kleurwisselingen, draaiende randen |
| `transform` op een laag | Meestal alleen samenstellen | Grote achtergronden over het hele scherm |
| `opacity`-crossfade | Meestal alleen samenstellen | Trage stemmings- of palet-wisselingen |

Opnieuw tekenen is prima op kleine vlakken. Geef bij grote vlakken de voorkeur aan transform en opacity.

Meet in plaats van te gokken. In Chrome DevTools toont het Rendering-paneel met paint flashing de vlakken die elk beeld opnieuw worden getekend, en een Performance-opname toont hoeveel van elk beeld naar tekenen gaat. [CSS-kleurverloopprestaties](https://gradiently.design/nl/guide/css-gradient-performance) loopt er stap voor stap doorheen.

## Verminderde beweging en goede manieren

Sommige mensen worden duizelig of afgeleid van achtergrondbeweging, en besturingssystemen laten hen om minder vragen. Respecteer dat met een `prefers-reduced-motion`-query die de animatie stopt en een stil, af beeld overlaat. De gids over [verminderde beweging](https://gradiently.design/nl/guide/reduced-motion) legt uit wat als beweging telt die het weghalen waard is.

```css
@media (prefers-reduced-motion: reduce) {
  .hero,
  .hero::before,
  .sky::after {
    animation: none;
  }
}
```

Eén regel die elke techniek hierboven stopt. Controleer dat het beeld dat overblijft er nog goed uitziet.

### Vermijden

- Cycli sneller dan ongeveer 8 seconden op grote vlakken
- Regenboogtintrotatie over de hele pagina
- Beweging achter lopende tekst die mensen moeten lezen
- Animaties die blijven draaien als het tabblad minutenlang inactief is

### Doen

- Trage, sfeervolle beweging binnen één kleurfamilie
- Beweging in de hero, stilte in de inhoud
- Een rustig stilstaand beeld voor verminderde beweging
- Testen op een bescheiden laptop en telefoon, niet alleen op een snelle desktop

## FAQ

### Kun je een CSS-kleurverloop animeren?

Niet direct: browsers springen tussen twee kleurverloopwaarden in keyframes. Animeer in plaats daarvan `background-position`, geregistreerde aangepaste eigenschappen in het kleurverloop of de transform en opacity van een kleurverloopblaag.

### Wat is de vloeiendste manier om een kleurverloopachtergrond te animeren?

`transform` of `opacity` animeren op een aparte kleurverloopblaag, omdat browsers die meestal zonder opnieuw tekenen aankunnen.

### Hoe animeer ik kleurverloopkleuren in CSS?

Registreer elke kleur met `@property` met `syntax: "<color>"`, gebruik de eigenschappen in het kleurverloop en verander ze in `@keyframes`.

### Maken geanimeerde kleurverlopen een pagina traag?

Kleine zelden. Grote geanimeerde achtergronden die elk beeld opnieuw tekenen kunnen batterij en vloeiendheid kosten, dus geef de voorkeur aan transform of opacity en meet met DevTools.

### Hoe respecteer ik verminderde beweging bij kleurverloopanimaties?

Zet een `animation: none`-regel in `@media (prefers-reduced-motion: reduce)`, zodat gebruikers die om minder beweging vragen een stilstaand beeld zien.
