Alt i perspektiv: Ren CSS-parallax og andre rulleffekter

Følg med ved hjælp af disse Codepens:

Grundlæggende parallax
Parallax med fast objekt

På trods af påstande om, at "parallax er død," er effekten meget levende og godt - og fængslende - når den implementeres korrekt. Desværre, ni gange ud af ti, er implementeringen forbløffet i Javascript. At spille med lyttere til rullebegivenheder er risikabel forretning for ydeevne, og at ændre DOM direkte udløser unødvendige gengivelser, hvilket forårsager hakke animationer og klistrede ruller. Korrekt parallax kan trækkes af ved hjælp af JS. Her er en fremragende artikel om, hvordan det skal gøres:

Men til enklere rulleanimationer er brug af ren CSS en idiotsikker, performant tilgang.

Den grundlæggende opsætning

Som et første eksempel vil vi oprette en side med et parallaxhoved og et statisk sideindhold. Fordi vi nedgraverer Javascript, har vi ikke adgang til vinduets rulleposition, og vi behøver ikke det! Nøglen til at trække effekten ud er at drage fordel af perspektivet. Vi opretter 2 lag indhold. Det indhold, vi vil rulle langsommere, vil blive placeret "længere" væk fra brugeren på z-aksen. Dette vil tvinge browseren til at gøre alt det tunge løft for os.

Her er den grundlæggende markering:

  
    

Overskrift      
    

Webstedsindhold

  

Lad os kødes ud af CSS. Vi er nødt til at bede browseren om at drage fordel af perspektiv langs z-aksen. Det gør vi ved at føje den perspektiviske egenskab til vores indpakningsklasse:

perspektiv: 1px;

En større perspektivværdi medfører en større forskel i rullehastigheder mellem lagene.

Dernæst tvinger vi indpakningen til at optage 100% af browserens visningsport og indstille overflow-y til auto. Dette gør det muligt for indhold i indpakningen at rulle som sædvanligt, men rullehastigheden for efterkommere vil nu være i forhold til indpakningens perspektivværdi:

.indpakning {
  højde: 100vh;
  overflow-x: skjult;
  overløb-y: auto;
  perspektiv: 1px;
}

Den første div vil indeholde vores headerindhold. Baggrundsbilledet, der anvendes på et pseudoelement, placeres en pixel “væk” fra brugeren på z-aksen, mens indholdet er på niveau med resten af ​​siden og ruller med normal hastighed.

Intet for specielt sker i .sektionsklassen, der anvendes til overskriften. Det definerer højden og formaterer indholdet. Her er CSS:

.afsnit {
  højde: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  skriftstørrelse: 48px;
  farve: hvid;
}

Al parallaxens godhed sker i pseudo-elementet:

.parallax :: efter {
  indhold: " ";
  position: absolut;
  top: 0;
  højre: 0;
  bund: 0;
  venstre: 0;
  transform: translateZ (-1px) skala (2);
  baggrundstørrelse: 100%;
  z-indeks: -1;
  baggrund-billede: url (nogle link til et billede);
}

Pseudo-elementet placeres bag indholdet af header. translateZ (-1px) definerer lagets afstand fra brugeren langs z-aksen.

Fordi vi flytter laget længere tilbage, vises indholdet mindre (tænk over, hvad der sker, når du flytter et objekt væk fra dig). For at redegøre for dette skal vi skalere laget tilbage til størrelse ved hjælp af skala (2).

Hvis dit perspektiv er indstillet til 1px, er formlen til at skalere lag tilbage til deres standardstørrelse: 1 + (translateZ * -1) / perspektiv.

I vores tilfælde ville en translateZ (-2px) kræve en skala (3) og så videre ...

Tilføj noget statisk indhold under overskriften, så får du en smuk parallakseffekt uden JS behov!

Her er et link til Codepen for dette eksempel.

Nu til den sjove del: Parallax med fast objekt

Grundlæggende parallax er stor. Det indånder liv i en ellers statisk webside. Men du kan gøre så meget mere med perspektiv i CSS. Dette blev klart for mig, når jeg arbejdede på en rulleanimation til min porteføljeside.

Jeg ville have, at en stak SVG-lego-klodser skulle gå i stykker ved forskellige hastigheder, da brugeren rullede ned på min hjemmeside. Efter at have fiklet med JS i et stykke tid, indså jeg, at denne effekt kunne opnås med ren CSS - og være smøragtig glat på det!

Tanken er at oprette separate lag af objekter i masterbeholderen, hver med en anden translateZ-værdi (læse: rullehastighed). Mens jeg implementerede dette, indså jeg hurtigt, at jeg ved oversættelse og skalering af objekterne ikke havde nogen måde at holde styr på deres x- og y-positioner (de ville ændre sig i forhold til objektets translateZ-værdi). For at løse dette indpakket jeg hvert objekt i en klar beholder, der passer til hele skærmen. Jeg kunne derefter placere objektet nøjagtigt i indpakningen og anvende translateZ og skalaen på indpakningen i stedet for selve objektet.

Kun en. Indpakningsklasse er nødvendig for at definere størrelsen for alle objekter:

.object-wrapper {
  position: absolut;
  top: 0;
  højre: 0;
  bund: 0;
  venstre: 0;
  baggrund: ingen;
  justify-content: center;
}

Forskellige hastigheder kan derefter defineres og anvendes på objektindpakningerne:

.speed-1 {
  transform: translateZ (-1px) skala (2);
}
.speed-2 {
  transform: translateZ (-2px) skala (3);
}
.speed-3 {
  transform: translateZ (-3px) skala (4);
}

Her er en Codepen, der demonstrerer Parallax med fast objekt:

Pure CSS tilbyder en verden af ​​muligheder for at animere indhold i forhold til rullepositionen - og det bedste er, at når JS grøftes, er det næsten umuligt at ødelægge ydelsen!

Når det kommer til udøvende parallax, handler det virkelig om perspektiv.