Vårstäda din webbplats: Animationer

När våren kommer passar många på att storstäda hemma. Vi delar med oss av några tips på hur du kan ge din webbplats kodbas en vårstädning genom att gno bort gammal JavaScript-kod och ersätta den med putsade, moderna standardlösningar.

Fönsterputsskrapa skrapar bort kod framför en blå himmel

Animationer

I och med CSS3 fick vi möjlighet att animera HTML-element med CSS keyframes-animationer och transitions. Trots detta har JavaScript i stor utsträckning använts för att skapa animationer. För mer avancerad animering är det en god idé att använda bibliotek som GSAP eller Anime.js men för enklare animationer är det ofta onödigt att ladda in ett stort JavaScript-bibliotek.

Det finns anledningar till att JavaScript använts för animationer istället för CSS, några av dessa är:

  1. Det har endast varit möjligt att animera med fasta värden som 100px.
  2. Det har inte varit möjligt att animera dolda element till synliga (om de varit dolda med display: none).
  3. Det har varit svårt att kombinera animationer.

Alla dessa går dock att göra med CSS idag.

Animera till auto-höjd eller bredd

Att animera ett HTML-elements storlek har länge varit möjligt med CSS-animationer, så länge storleken på elementet är känd. Men om innehållets bredd eller höjd inte är känd eller varierar har det tidigare inte varit möjligt att exempelvis animera en utfällbar sektion från dold till utfälld. Det är lätt att tro att det fungerar att ange height: 0 och sedan animera till height: auto men detta har inte fungerat eftersom CSS endast tillåtit animeringar med exakta värden. Lösningen har då ofta varit att använda JavaScript för att animera.

Nu går det att animera ett elements storlek utifrån innehållets storlek genom att använda CSS-egenskapen interpolate-size: allow-keywords. Detta instruerar webbläsaren att det ska vara tillåtet att animera nyckelord, inte bara värden. Webbläsaren kan nu animera med värden som auto eller max-content.

Exempel på Details-element med animering

:root {
  interpolate-size: allow-keywords;
}

::details-content {
  transition: height .25s ease-in-out;
  height: 0;
  overflow: clip;
}
    
[open]::details-content {
  height: auto;
}

Se exempel på animering av details-element på CodePen

Varför måste interpolate-size anges? Vore det inte bättre att använda detta som standard? Det handlar om bakåtkompabilitet. Att införa en förändring som denna skulle kunna förstöra existerande webbsidor.

Animera från och till dolt innehåll

Ett av de största problemen med CSS-animationer har varit display: none som växlar ett element från synligt till osynligt. Tyvärr gör detta att animationer som ska starta när elementet blir synligt hoppar direkt till slutet av animationen.

Exemepel på CSS-animation från opacitet 0 till 100%.

.notification {
  display: none;
  opacity: 0;
  transition: opacity .25s ease;

  &.show {
    display: block;
    opacity: 1;
  }
}

Tyvärr skulle denna animation inte fungera eftersom display ändras från none till block. Att inte använda display: none löser problemet. Men då har vi istället skapat ett tillgänglighetsproblem. Innehåll med opacity 0 går nämligen att komma åt med tangentbordsnavigation, vilket kan innebära att användare exempelvis kan tabba sig till en osynlig länk eller att skärmläsare läser upp dolda statusmeddelanden. Därför är det viktigt att alltid dölja innehåll med display: none (eller hidden-attributet).

Trick för att lösa detta är att istället använda visibility: hidden eller animera med JavaScript.

För att lösa detta kan vi använda CSS transition-behavior och @starting-style.

Genom att ange: transition-behavior: allow-discrete aktiveras möjligheten att animera förändringar av display och content-visibility.

.notification {
  transition: opacity .25s ease, 
    display .25s ease allow-discrete;
}

CSS @starting-style används för att beskriva starvärden för ett element som ska använda transitions. Det används för att transformera element direkt när sidan laddas, när element läggs till på sidan eller när elementets display ändras.

@starting-style {
  .notification.show {
    height: 0;
  }
}

Om vi lägger ihop dessa får vi en fungerande animation från och till display: none.

Exempel på fungerande CSS-animation av opacitet från 0 till 100% med display: none

.notification {
  display: none;
  opacity: 0;
  transition: opacity ease .25s, 
    display .25s;
  transition-behavior: allow-discrete;

  &.show {
    display: block;
    opacity: 1;

    @starting-style {
      display: none;
      opacity: 0;
    }
  }
}

Exempel på animation med display: none på CodePen

Webbläsarstöd

Interpolate-size fungerar idag bara i Chromium-webbläsare som Chrome, Vivaldi och Edge och har därmed Baseline Limited availability.

Transition-behaviour och @starting-style fungerar i alla webbläsare och är markerade som Baseline Newly available.

I regel går det bra att använda dessa redan idag då äldre webbläsare forfarande kommer visa och dölja innehållet. Det är bara själva animationen som inte fungerar.

Kombinera animationer

Ett klassiskt problem med CSS har varit att kombinera animationer. Om ett element redan är transformerat från start har det krävts att transformationerna upprepas eller att dela upp elementet i flera HTML-element med varsin animation.

Exempelvis om ytterligare transformation ska läggas till vid hover-state. Transformationen som används vid hover kommer skriva över och ersätta grund-transformationen. Vid hover-state försvinner då rotationen.

.box {
  width: 100px;
  height: 100px;
  background-color: dodgerblue;
  transform: rotate(45deg);
  transition: all .5s ease;
  
  &:hover {
    transform: scale(1.5);
  }
}

Med CSS animation-composition finns de nu större möjligheter att kombinera animationer. Genom att ange animation-composition: add går det att instruera webbläsaren att animationerna ska kombineras.

Det går numera även att använda transformationer som separata egenskaper. Det går då enklare att kombinera olika transformationer som rotate och scale.

.box {
  width: 100px;
  height: 100px;
  background-color: dodgerblue;
  rotate: 45deg;
  transition: all .5s ease;
  
  &:hover {
    scale: 1.5;
  }
}

Du hittar fler tips i artikelserien Vårstäda din webbplats.

Publicerad:
Andreas Nylin, porträtt

Andreas Nylin

Senior gränssnittsutvecklare och tillgänglighetsexpert