# CSS-animerede gradientbaggrunde, gjort ordentligt

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

Gradienter kan ikke animeres direkte, men alt omkring dem kan. Fire teknikker, hvad hver koster browseren, og hvordan du holder bevægelsen rolig og valgfri.

## The short version

- Browsere kan ikke interpolere mellem to gradientværdier, så en CSS-animeret gradient flytter, fader eller transformerer gradienten i stedet for at animere den direkte.
- Den klassiske teknik gør baggrunden større end elementet og animerer background-position, hvilket virker overalt, men gentegner hver frame.
- Ved at registrere brugerdefinerede egenskaber med @property kan browseren animere enkelte farver, vinkler og positioner inde i en gradient.
- At animere transform eller opacity på et separat gradientlag er som regel den billigste løsning, fordi browsere ofte kan sammensætte det uden at gentegne.
- Hver gradientanimation bør stoppe eller blive næsten stille, når brugeren har bedt om reduceret bevægelse.

En **CSS-animeret gradient** er en gradientbaggrund, der skifter farve eller position over tid. Der er en hage: skriver du to forskellige gradienter i en `@keyframes`-regel, blander browsere ikke mellem dem, de springer. Derfor animerer hver teknik, der virker, noget ved siden af gradienten: dens position, de brugerdefinerede egenskaber inde i den eller laget, den er malet på. Hvilken du vælger, afgør, hvor blød den ser ud, og hvor meget arbejde browseren har med hver frame.

- Frame 1: skumring: `linear-gradient(120deg, #1e1b4b, #7c3aed 45%, #f472b6)`
- Frame 2: senere: `linear-gradient(160deg, #1e1b4b, #6d28d9 35%, #fb7185)`
- Frame 3: gløder: `linear-gradient(200deg, #1e1b4b, #4c1d95 30%, #fb923c)`

Tre øjeblikke af én langsom animation. Både retning og farve bevæger sig, men paletten forbliver i én familie.

For designsiden, altså hvornår bevægelse hjælper et brand, og hvordan du timer den, se [animerede gradientbaggrunde](https://gradiently.design/da/guide/animated-gradient-background). Denne guide er koden.

## Teknik 1: flyt en overstor baggrund

Gør gradienten to til fire gange så stor som elementet med `background-size`, og animér derefter `background-position`, så en anden del af den vises over tid. Den virker i alle browsere og kræver ingen JavaScript. Brug `alternate`, så bevægelsen vender jævnt i stedet for at springe tilbage til starten.

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

Den klassiske animerede gradient. Langsomme varigheder på 12 til 30 sekunder føles som stemning frem for uro.

Prisen: `background-position` kan browsere ikke flytte alene på grafikkortet, så elementet gentegnes ved hver frame. På en knap er det ingenting. På en helskærmshero er det reelt arbejde, der kører, så længe siden er åben.

## Teknik 2: animér farvestop med @property

Brugerdefinerede egenskaber er normalt strenge, som ikke kan interpoleres. Registrerer du en med `@property`, får den en type, som `<color>`, `<angle>` eller `<percentage>`, og typede egenskaber animeres jævnt. Brug dem inde i gradienten, og du kan animere farverne, vinklen eller et stops position direkte. `@property` understøttes i alle nuværende større browsere. Tjek [caniuse](https://caniuse.com/mdn-css_at-rules_property), hvis du understøtter ældre.

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

Farver og vinkel animeres inde i gradienten. Uregistrerede egenskaber ville springe i stedet for at blande.

- Start: violet til pink: `linear-gradient(120deg, #7c3aed, #f472b6)`
- Slut: cyan til orange: `linear-gradient(200deg, #0891b2, #fb923c)`

De to ender af animationen ovenfor. Browseren blander hver frame imellem.

Denne teknik gentegner stadig hver frame, ligesom den første. Fordelen er kontrol: du kan flytte ét skær i en [mesh-gradient](https://gradiently.design/da/guide/css-mesh-gradient), rotere en [konisk kant](https://gradiently.design/da/guide/css-gradient-border) eller skifte en brandgradient mod en anden palet uden overstore baggrunde.

## Teknik 3: transformér et gradientlag

Læg gradienten på et pseudoelement, der er meget større end elementet, og animér dets `transform`, for eksempel en langsom rotation eller drift. Browsere kan som regel flytte et transformeret lag på grafikkortet uden at gentegne det, så det er den billigste måde at animere en stor gradient på. `will-change: transform` antyder, at laget bør promoveres på forhånd.

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

En enorm konisk gradient, der drejer langsomt bag indholdet. Den negative inset holder hjørnerne dækket, mens den roterer.

## Teknik 4: krydsfade to gradienter

Stak to gradientlag, og animér `opacity` på det øverste. Opacity er også en egenskab, der egner sig til compositoren, så fadet er jævnt og billigt. Det passer til langsomme stemningsskift, som en dagpalet, der fader over i en natpalet, og det lader de to gradienter være helt forskellige i opbygning.

```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 fader til nat og tilbage. Kun opacity ændres, så intet gentegnes.

## Sådan vælger du en teknik

| Teknik | Browserens arbejde pr. frame | Bedst til |
| --- | --- | --- |
| Flytning af `background-position` | Gentegning | Små elementer, knapper, tekst |
| `@property`-farver og vinkler | Gentegning | Præcise farveskift, roterende kanter |
| `transform` på et lag | Som regel kun sammensætning | Store baggrunde i fuld skærm |
| `opacity`-krydsfade | Som regel kun sammensætning | Langsomme stemnings- eller paletskift |

Gentegning er fint på små områder. Til store områder bør du foretrække transform og opacity.

Mål i stedet for at gætte. I Chrome DevTools fremhæver panelet Rendering med paint flashing de områder, der gentegnes hver frame, og en Performance-optagelse viser, hvor stor en del af hver frame der går til tegning. [CSS-gradienters ydeevne](https://gradiently.design/da/guide/css-gradient-performance) gennemgår det.

## Reduceret bevægelse og god opførsel

Nogle mennesker bliver svimle eller forstyrrede af bevægelse i baggrunden, og operativsystemer lader dem bede om mindre af den. Respektér det med en `prefers-reduced-motion`-forespørgsel, der stopper animationen og efterlader en stille, færdig frame. Guiden om [reduceret bevægelse](https://gradiently.design/da/guide/reduced-motion) forklarer, hvad der tæller som bevægelse, det er værd at fjerne.

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

Én regel, der stopper alle teknikkerne ovenfor. Tjek, at den frame, der efterlades, stadig ser rigtig ud.

### Undgå

- Cyklusser hurtigere end omkring 8 sekunder på store områder
- Regnbueagtig farvetonerotation over hele siden
- Bevægelse bag brødtekst, folk skal læse
- Animationer, der bliver ved med at køre, når fanen har stået ubrugt i minutter

### Gør

- Langsom, stemningsskabende bevægelse inden for én farvefamilie
- Bevægelse i heroen, ro i indholdet
- En rolig stille frame til reduceret bevægelse
- Test på en beskeden laptop og en telefon, ikke kun på en hurtig stationær

## FAQ

### Kan man animere en CSS-gradient?

Ikke direkte: browsere springer mellem to gradientværdier i keyframes. Animér i stedet `background-position`, registrerede brugerdefinerede egenskaber brugt inde i gradienten eller transform og opacity på et gradientlag.

### Hvad er den blødeste måde at animere en gradientbaggrund på?

At animere `transform` eller `opacity` på et separat gradientlag, fordi browsere som regel kan håndtere dem uden at gentegne.

### Hvordan animerer jeg gradientfarver i CSS?

Registrér hver farve med `@property` med `syntax: "<color>"`, brug egenskaberne i gradienten, og ændr dem i `@keyframes`.

### Gør animerede gradienter en side langsom?

Små betyder sjældent noget. Store animerede baggrunde, der gentegnes hver frame, kan koste batteri og jævnhed, så foretræk transform eller opacity, og mål med DevTools.

### Hvordan respekterer jeg reduceret bevægelse i gradientanimationer?

Pak en `animation: none`-regel ind i `@media (prefers-reduced-motion: reduce)`, så brugere, der beder om mindre bevægelse, ser en stille frame.
