# Animation

## Hvad det er

På nettet er en animation oftest en CSS-animation: en navngiven række
keyframes, skrevet én gang i en `@keyframes`-regel og knyttet til et element
gennem `animation`-egenskaberne. W3C's specifikation CSS Animations Level 1
beskriver mekanismen som en måde »to animate the values of CSS properties over
time, using keyframes«, altså at animere egenskabernes værdier over tid ved
hjælp af keyframes. Animerede billeder, video og tegning på et canvas bevæger
sig også; denne artikel følger den deklarative slags.

Hver keyframe angiver egenskabsværdier på et punkt i forløbet: `from` eller
`0%` ved starten, `to` eller `100%` ved slutningen og eventuelle procenter
imellem. Browseren udfylder værdierne mellem dem. De øvrige
animationsegenskaber bestemmer, hvor længe ét forløb varer, hvor mange gange
det gentages, om hvert andet forløb spilles baglæns, og om animationen kører
eller er sat på pause. Med `infinite` som antal gentagelser gentages
animationen ifølge specifikationen for evigt. `animation-fill-mode` afgør, hvad
elementet viser uden for forløbet: med `none` har animationen ingen virkning
dér, `backwards` anvender den første keyframe under en eventuel forsinkelse, og
`forwards` beholder de værdier, animationen sluttede med.

En overgang, på engelsk transition, er den nære slægtning: hvor en ændret
egenskabsværdi normalt vises med det samme, fordeler CSS Transitions ændringen
over en fastsat varighed. CSS Animations trækker grænsen mellem de to:
overgange udløses implicit, når en egenskabsværdi ændrer sig, mens animationer
udføres eksplicit, når animationsegenskaberne anvendes. Et link, der toner sin
farve, når musen holdes over det, er en overgang; en indlæsningsindikator, der
drejer, uanset om noget har ændret sig, er en animation.

En nyere specifikation, Scroll-driven Animations, bytter uret ud med selve
siden. En animation, der er knyttet til en tidslinje for scrollfremskridt,
skrider frem, mens en scroll-container scrolles, fra 0 % i starten af det
scrollbare område til 100 % ved enden. Falder de to positioner sammen, fordi
der intet er at scrolle, kalder specifikationen tidslinjen inaktiv.

## Hvorfor det betyder noget

Bevægelse trækker opmærksomheden til sig, og det er både grunden til at bruge
den og problemet med den.

**For nogle læsere er den fysisk ubehagelig.** Understanding-dokumentet til
succeskriterium 2.3.3 i WCAG 2.2 forklarer, at elementer, der bevæger sig,
mens en side scrolles, kan udløse reaktioner hos mennesker med vestibulære
lidelser, altså lidelser i det indre øre: svimmelhed, kvalme og hovedpine. Det
nævner parallakse-scrolling, hvor baggrunde bevæger sig i et andet tempo end
forgrunden, som en animation, der ofte er unødvendig, og bemærker, at
virkningen kan være så alvorlig, at det kræver sengeleje at komme sig.

**Læseren kan sige det, og siden kan spørge.** Media Queries Level 5 definerer
`prefers-reduced-motion`, en mediefunktion med to værdier. `reduce` betyder, at
læseren har bedt systemet om en brugerflade, der fjerner eller erstatter de
former for bevægelsesbaseret animation, som giver ubehag hos mennesker med
vestibulær følsomhed over for bevægelse eller distraherer mennesker med
opmærksomhedsvanskeligheder. `no-preference` betyder, at der ikke er nogen kendt
præference, og værdien evalueres som falsk, når funktionen testes alene.

**To succeskriterier dækker det.** 2.2.2 Pause, Stop, Hide på niveau A gælder
indhold, der bevæger sig, blinker eller ruller, starter automatisk, varer mere
end fem sekunder og vises sammen med andet indhold: læseren skal have en måde
at sætte det på pause, stoppe det eller skjule det på, medmindre bevægelsen er
afgørende. Kriteriet gælder alt på siden, og en animation, der kun stopper,
mens fokus hviler på den, tæller ikke som en pause. 2.3.3 Animation from
Interactions på niveau AAA kræver, at bevægelsesanimation, som en interaktion
udløser, kan slås fra, medmindre den er afgørende. Understanding-dokumentet
nævner funktionen til reduceret bevægelse i browseren eller styresystemet som
én måde at opfylde det på.

**Ikke enhver ændring er bevægelse.** WCAG definerer bevægelsesanimation som
trin, der føjes ind mellem to tilstande for at skabe en illusion af bevægelse
eller en fornemmelse af en jævn overgang. Et element, der glider på plads
eller skifter størrelse, mens det dukker op, er animeret; et, der dukker op
med det samme, er ikke. En ændring af farve eller uigennemsigtighed, som lader
elementets opfattede størrelse, form og placering være, falder uden for
definitionen, og derfor betyder reduceret bevægelse ikke, at hver toning skal
fryses.

## Sådan ser det ud i praksis

Den tydeligste lektie begynder med en regel, der så færdig ud. Sitet
respekterede præferencen for reduceret bevægelse med én universel regel, der
slog alle overgange fra; den så komplet ud og bestod linteren, men med en
emuleret præference animerede elleve selektorer stadig. Arbejdet, der
[sikrede, at reduceret bevægelse virker](/da/portfolio/made-reduced-motion-honest-135/),
fandt årsagen i specificiteten: en universel selektor taber til enhver regel med
en klasse, og det er hver eneste gennemtænkte animation på siden. Alt, der
bevæger sig, ligger nu i én sen del af stylesheetet, og en linter afviser en
overgang på transform alle andre steder. Grænsen går ved bevægelse, ikke farve,
så en farveovergang består, og en overgang på bevægelse gør ikke. Bevægelse
udtrykkes desuden som en overgang og ikke som en keyframe-animation, fordi den
første trivielt kan afbrydes, og den anden ikke kan. Som siden siger, fejler en
regel, der taber på specificitet, i stilhed.

Scroll-drevet bevægelse har sin egen fejl. Blandt de
[11 tilgængelighedsfejl, som browseren meldte i orden](/da/portfolio/fixed-11-accessibility-defects-the-browser-called-healthy-131/),
var en scroll-drevet animation, der er inaktiv på en side for kort til at
scrolle, og som permanent klippede footeren af på tre sider. De automatiske
regler havde godkendt den, fordi fejlen lå i, hvordan siden blev gengivet, og
ikke i markuppen.

En linter kan gøre tjekket umuligt at springe over. Et
[designsystem med 48 tokens](/da/portfolio/built-a-48-token-design-system-160/),
bygget på platformens eget glasmateriale, har bevægelse som én af sine seks
tokengrupper, og dets linter afviser en animation, der er erklæret uden at
respektere præferencen for reduceret bevægelse. Siden giver grunden: en
animation tilføjes under finpudsningen, præferencetjekket er den del, der
bliver sprunget over, og derfor gør reglen animationen umulig at skrive uden
det.

Dette sites stylesheets viser de samme vaner andre steder. De to tandhjul i
toppen af siden drejer i løkker på 60 og 96 sekunder, og begge sættes til
`animation: none` under `reduce`. Deres scroll-koblede parallakse er beskyttet
to gange, inden for `prefers-reduced-motion: no-preference` og inden for en
`@supports`-test af `animation-timeline: scroll()`; i en browser uden
funktionen bliver tandhjulene, hvor de er, og kommentaren kalder netop det
designet. I footeren får kreditblokken, som rummer copyrighten, sin skjulte
tilstand fra animationens baglæns udfyldning og ikke fra en erklæret
`opacity: 0`. Kommentaren giver grunden: en inaktiv tidslinje har ingen
virkning overhovedet, og den gamle `opacity: 0` skjulte copyrighten på hver
kort side.

## Hvor det går galt

- **Slukknappen taber kaskaden.** En generel `transition: none` på den
  universelle selektor har næsten ingen specificitet, så enhver regel med en
  klasse bliver ved med at bevæge sig, uden at noget melder det. En blok
  placeret efter de regler, den skal slå, og som nævner de bevægelige
  selektorer, får den stille tilstand til at vinde.
- **Præferencen kommer senere eller aldrig.** En animation i basisstilen
  bevæger sig for alle, indtil nogen husker at slå den fra. Erklæres den inden
  for `@media (prefers-reduced-motion: no-preference)`, er stilstand
  udgangspunktet.
- **En scroll-tidslinje møder en side uden noget at scrolle.** Tidslinjen er
  inaktiv, og animationen gør intet, så en starttilstand skrevet ind i
  basisstilen, for eksempel en `opacity: 0`, der venter på at blive animeret
  væk, bliver stående. En starttilstand fra den baglæns udfyldning forsvinder
  sammen med animationen.
- **En keyframe-værdi, som browseren afviser, falder stille ud.**
  Specifikationen siger, at en egenskab, der er angivet, men ugyldig i en
  keyframe, animeres, som om den keyframe ikke fandtes. En stavefejl i en værdi
  springer et trin over uden nogen fejlmeddelelse.
- **En dekorativ løkke kører uden mulighed for at stoppe den.** En
  `infinite`-animation, der starter ved indlæsning ved siden af teksten, falder
  ind under 2.2.2, når den har kørt i mere end fem sekunder; en pauseknap eller
  en afslutning inden for fem sekunder opfylder kriteriet.
- **»Reducér« læses som »fjern alt«.** At skære hver tilstandsændring væk kan
  tage information med sig sammen med bevægelsen. At vise den nye tilstand med
  det samme eller med en toning bevarer informationen og dropper bevægelsen.

## Læs mere

- [CSS Animations Level 1](https://www.w3.org/TR/css-animations-1/)
  — `@keyframes`-reglen, animationsegenskaberne, udfyldningstilstande og de
  hændelser, en animation udsender.
- [CSS Transitions Level 1](https://www.w3.org/TR/css-transitions-1/)
  — hvordan en ændret egenskabsværdi fordeles over en varighed i stedet for at
  slå igennem med det samme.
- [Scroll-driven Animations](https://www.w3.org/TR/scroll-animations-1/)
  — tidslinjer for scrollfremskridt, notationen `scroll()` og de tilfælde, hvor
  en tidslinje er inaktiv.
- [Media Queries Level 5: prefers-reduced-motion](https://www.w3.org/TR/mediaqueries-5/#prefers-reduced-motion)
  — de to værdier, og hvad en læser, der vælger `reduce`, beder om.
- [Understanding SC 2.2.2: Pause, Stop, Hide](https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html)
  — grænsen på fem sekunder, hvad der tæller som automatisk start, og hvilke
  pausemekanismer der gælder.
- [Understanding SC 2.3.3: Animation from Interactions](https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions.html)
  — vestibulære reaktioner, parallakse og præferencen for reduceret bevægelse
  som én måde at opfylde kriteriet på.

<https://engineer.company/da/glossary/animation/>
