Animation
en förändring i en sidas utseende som spelas upp över tid
Vad det är
På webben är en animation oftast en CSS-animation: en namngiven följd av nyckelbilder (keyframes)
som skrivs en gång i en @keyframes-regel och kopplas till ett element genom egenskaperna
animation. W3C:s specifikation CSS Animations Level 1 beskriver mekanismen som ett sätt att
animera värdena hos egenskaper i CSS över tid med hjälp av nyckelbilder. Animerade bilder, video och
ritning på en canvas rör sig också, men den här artikeln följer den deklarativa sorten.
Varje nyckelbild anger egenskapernas värden vid en punkt i förloppet: from eller 0% i början,
to eller 100% i slutet och valfria procenttal däremellan. Webbläsaren räknar fram värdena mellan
dem. De övriga animationsegenskaperna styr hur länge ett varv varar, hur många gånger det upprepas,
om vartannat varv spelas baklänges och om animationen körs eller är pausad. Antalet infinite
betyder, med specifikationens ord, att animationen upprepas för evigt. animation-fill-mode avgör
vad som syns utanför förloppet: med none har animationen ingen verkan då, backwards tillämpar
den första nyckelbilden under en eventuell fördröjning, och forwards behåller värdena som den
slutade på.
En övergång (transition) är den nära släktingen. Där ett ändrat egenskapsvärde annars skulle synas direkt sprider CSS Transitions ut ändringen över en angiven tid. CSS Animations drar gränsen mellan de två: övergångar utlöses underförstått när ett egenskapsvärde ändras, medan animationer körs uttryckligen när animationsegenskaperna tillämpas. En länk som tonar sin färg när pekaren hålls över den är en övergång. En laddningssnurra som snurrar vare sig något har ändrats eller inte är en animation.
En nyare specifikation, Scroll-driven Animations, byter ut klockan mot själva sidan. En animation som är kopplad till en tidslinje för rullningsförlopp (scroll progress timeline) går framåt när en rullningsbehållare rullas, från 0 % i början av det rullbara intervallet till 100 % i slutet. När de två lägena sammanfaller, eftersom det inte finns något att rulla, kallar specifikationen tidslinjen inaktiv.
Varför det spelar roll
Rörelse drar till sig uppmärksamhet, och det är både skälet att använda den och problemet med den.
För en del läsare är den fysiskt obehaglig. Förklaringsdokumentet (Understanding) till framgångskriteriet 2.3.3 i WCAG 2.2 beskriver hur element som rör sig när en sida rullas kan utlösa reaktioner hos personer med vestibulära störningar, alltså besvär från balansorganet i innerörat: yrsel, illamående och huvudvärk. Dokumentet nämner parallaxrullning, där bakgrunden rör sig i en annan takt än förgrunden, som en animation som ofta inte är nödvändig, och påpekar att besvären kan bli så svåra att den drabbade behöver sängvila för att återhämta sig.
Läsaren kan säga ifrån, och sidan kan fråga. Media Queries Level 5 definierar
prefers-reduced-motion, en mediefunktion med två värden. reduce betyder att läsaren har bett
systemet om ett gränssnitt som tar bort eller ersätter de typer av rörelsebaserad animation som
orsakar obehag för personer med vestibulär rörelsekänslighet eller distraherar personer med
uppmärksamhetsstörningar. no-preference betyder att ingen preferens är känd, och värdet räknas som
falskt när funktionen testas ensam.
Två framgångskriterier täcker det. 2.2.2 Pause, Stop, Hide, på nivå A, gäller innehåll som rör sig, blinkar eller rullar, som startar automatiskt, varar längre än fem sekunder och visas tillsammans med annat innehåll: läsaren behöver ett sätt att pausa, stoppa eller dölja det, om inte rörelsen är nödvändig. Kriteriet gäller allt på sidan, och en animation som stannar bara medan fokus vilar på den räknas inte som en paus. 2.3.3 Animation from Interactions, på nivå AAA, kräver att rörelseanimation som utlöses av en interaktion går att stänga av, om den inte är nödvändig. Förklaringsdokumentet nämner webbläsarens eller operativsystemets inställning för minskad rörelse som ett sätt att uppfylla kriteriet.
Rörelse är en snävare kategori än förändring. WCAG definierar rörelseanimation som steg som läggs till mellan två tillstånd för att skapa en illusion av rörelse eller en känsla av mjuk övergång. Ett element som glider på plats eller ändrar storlek när det visas är animerat. Ett som dyker upp direkt är det inte. En ändring av färg eller opacitet som lämnar elementets upplevda storlek, form och läge i fred faller utanför definitionen, och därför betyder minskad rörelse inte att varje toning ska frysas.
Så ser det ut i praktiken
Den tydligaste lärdomen börjar med en regel som såg färdig ut. Webbplatsen respekterade inställningen för minskad rörelse med en enda universell regel som stängde av alla övergångar. Den såg fullständig ut och passerade lintern, men under en emulerad inställning animerades fortfarande elva selektorer. Arbetet som gjorde inställningen för minskad rörelse ärlig spårade orsaken till specificitet: en universell selektor förlorar mot varje regel som bär en klass, och det är varje genomtänkt animation på sidan. Allt som rör sig ligger nu i en del av stilmallen som kommer sent, och en linter underkänner en transform med övergång var som helst annars. Gränsen som regeln drar är minska rörelse, inte färg, så en färgtoning godkänns och en övergång på rörelse gör det inte. Rörelse uttrycks också som en övergång snarare än som en keyframe-animation, eftersom den förra är trivial att avbryta och den senare inte är det. Som sidan uttrycker det: en regel som förlorar på specificitet fallerar i tysthet.
Rullningsstyrd rörelse har ett eget felläge. Bland de 11 tillgänglighetsbrister som webbläsaren rapporterade som felfria fanns en rullningsstyrd animation, inaktiv på en sida som var för kort för att rullas, som permanent hade skurit bort sidfoten på tre sidor. Webbplatsen klarade sina automatiska tillgänglighetsregler ändå, eftersom felet låg i hur sidan renderades och inte i vad uppmärkningen sade.
En linter kan göra kontrollen omöjlig att hoppa över. Ett designsystem med fyrtioåtta tokens, byggt på plattformens eget glasmaterial, har rörelse som en av sina sex grupper av tokens, och dess lintverktyg avvisar en animation som deklareras utan att respektera inställningen för minskad rörelse. Sidan anger skälet: en animation läggs till i ett ögonblick av finputsning, kontrollen av inställningen är den del som hoppas över, och därför gör regeln det omöjligt att skriva animationen utan den.
Den här webbplatsens stilmallar visar samma vanor på andra ställen. De två kugghjulen i sidhuvudet
snurrar ett varv på 60 respektive 96 sekunder, och båda får animation: none under reduce. Deras
rullningskopplade parallax är spärrad två gånger, inuti prefers-reduced-motion: no-preference och
inuti ett @supports-test för animation-timeline: scroll(). I en webbläsare som saknar
funktionen står kugghjulen kvar där de är, och kommentaren i koden kallar den reservlösningen för
själva designen. I sidfoten får rutan med upphovsrätten sitt dolda läge från animationens
bakåtfyllnad (backwards) i stället för från en deklarerad opacity: 0. Kommentaren förklarar
varför: en inaktiv tidslinje tillämpar ingenting alls, och den gamla opacity: 0 hade dolt
upphovsrätten på varje kort sida.
Var det går fel
- Avstängningen förlorar kaskaden. En generell
transition: nonepå den universella selektorn har nästan ingen specificitet, så varje regel med en klass fortsätter att röra sig, och ingenting rapporterar det. Ett block som placeras efter reglerna det måste slå, och som namnger de rörliga selektorerna, låter det stilla läget vinna. - Inställningen läggs till senare, eller aldrig. En animation i grundstilen rör sig för alla
tills någon kommer ihåg att stänga av den. Den som deklarerar animationen inuti
@media (prefers-reduced-motion: no-preference)gör stillhet till standardläget. - En rullningstidslinje möter en sida där det inte finns något att rulla. Tidslinjen är inaktiv
och animationen gör ingenting, så ett startläge som skrivits in i grundstilen, t.ex. en
opacity: 0som väntar på att animeras bort, ligger kvar. Ett startläge som kommer från bakåtfyllnaden försvinner tillsammans med animationen. - Ett värde som webbläsaren avvisar i en nyckelbild faller bort i tysthet. Specifikationen säger att en egenskap som anges men är ogiltig i en nyckelbild animeras som om den nyckelbilden inte fanns. Ett felstavat värde hoppar över ett steg utan något felmeddelande.
- En dekorativ loop snurrar utan något sätt att stoppa den. En
infinite-animation som startar när sidan laddas, bredvid texten, faller under 2.2.2 så fort den passerar fem sekunder. En pausknapp, eller ett slut inom fem sekunder, uppfyller kriteriet. - ”Minska” läses som ”ta bort allt”. Den som stryker varje tillståndsändring kan ta bort information tillsammans med rörelsen. Att visa det nya läget direkt, eller med en toning, behåller informationen och tar bort rörelsen.
Läs mer
- CSS Animations Level 1 — regeln
@keyframes, animationsegenskaperna, fyllnadslägena och de händelser som en animation skickar. - CSS Transitions Level 1 — hur en ändring av ett egenskapsvärde sprids ut över en tid i stället för att tillämpas direkt.
- Scroll-driven Animations — tidslinjer för
rullningsförlopp, notationen
scroll()och fallen där en tidslinje är inaktiv. - Media Queries Level 5: prefers-reduced-motion
— de två värdena och vad en läsare som väljer
reduceber om. - Understanding SC 2.2.2: Pause, Stop, Hide — gränsen på fem sekunder, vad som räknas som automatisk start och vilka sätt att pausa som duger.
- Understanding SC 2.3.3: Animation from Interactions — vestibulära reaktioner, parallax och inställningen för minskad rörelse som ett sätt att uppfylla kriteriet.