CSS og web

CSS-animerede gradientbaggrunde, gjort ordentligt

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.

GradientlyVerificeret Gradiently-konto··4 min. læsning
Forside: Pine Afternoon · GR·6MTX·YD

Kort fortalt

  • 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.
På denne side

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.

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. 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, 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.
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, rotere en konisk kant 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

TeknikBrowserens arbejde pr. frameBedst til
Flytning af background-positionGentegningSmå elementer, knapper, tekst
@property-farver og vinklerGentegningPræcise farveskift, roterende kanter
transform på et lagSom regel kun sammensætningStore baggrunde i fuld skærm
opacity-krydsfadeSom regel kun sammensætningLangsomme 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 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 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

Spørgsmål, folk stiller

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.

Del denne guide

Skrevet af GradientlyVerificeret Gradiently-konto

Holdet bag Gradiently, et designværktøj bygget om Marks: levende gradienter, der får alt, du designer, til at ligne dig.

Se vores profil