Műhely · vissza a rovathoz

Görgetésvezérelt animáció JS nélkül — és a csapda benne

A szekciók beúszásához évekig szkript kellett. Ma nem kell — cserébe viszont van egy hibalehetőség, ami nem hibaüzenettel jelentkezik, hanem üres lappal.

A görgetéshez kötött megjelenítés bevett megoldása sokáig az volt, hogy egy szkript figyelte, mikor ér egy elem a képernyőre, és akkor tett rá egy osztályt. Ez működik, de van vele két baj: szkriptet kell futtatni a fő szálon, és a hatás a görgetés ütemétől független — vagy elindult, vagy nem.

Erre való az animation-timeline: view(). Nem eseményre indít, hanem az idővonalat magát köti a görgetéshez: az animáció állapota abból következik, hol tart az elem a nézetben. Szkript nincs.

Amit ezzel megnyersz

Nincs megfigyelő, nincs eseménykezelő, és nincs az az apró akadás, ami a JavaScript-alapú megoldásoknál görgetés közben előfordul. A böngésző az egészet a saját animációs rétegében kezeli.

És — ami ennél fontosabb — nincs mit karbantartani. Egy CSS-tulajdonság nem évül el úgy, mint egy könyvtár, és nem kell hozzá semmilyen függőség.

És most a csapda

A hibát nem elméletből ismerem: a saját oldalamon találtam meg, jóval azután, hogy késznek hittem.

A jelenség a következő. A látogató legörget a lap aljára, átkattint egy másik oldalra, majd megnyomja a vissza gombot. A böngésző ilyenkor nem tölti újra a lapot, hanem memóriából állítja helyre — ez a bfcache, és pontosan azért van, hogy a visszalépés azonnali legyen.

Csakhogy a görgetéshez kötött idővonal ilyenkor nem feltétlenül számolódik újra. Az elemek a kezdő állapotukon ragadnak. Ha az a kezdőállapot opacity: 0, akkor a látogató egy üres lapra érkezik vissza — miközben a tartalom végig ott van a dokumentumban.

Mi történik visszalépéskor Normál betöltéskor az idővonal elindul és a tartalom megjelenik; memóriából visszaállítva az idővonal nem indul újra, és a tartalom a kezdő, átlátszó állapoton marad. normál betöltés lap betölt vissza gomb memóriából normál betöltés idővonal indul vissza gomb idővonal áll normál betöltés tartalom látszik vissza gomb üres lap a tartalom mindkét esetben ott van a dokumentumban
normál betöltéslap betölt
vissza gombmemóriából
normál betöltésidővonal indul
vissza gombidővonal áll
normál betöltéstartalom látszik
vissza gombüres lap

a tartalom mindkét esetben ott van a dokumentumban

A hiba azért alattomos, mert újratöltéssel nem reprodukálható. Aki a fejlesztés közben frissítget, sosem látja. Csak az valódi teszt, ha legörget, elnavigál, és a böngésző vissza gombjával jön vissza.

A védőháló, két rétegben

Az első réteg a visszalépés pillanatában újraindítja az animációkat: a pageshow esemény megmondja, hogy a lap a memóriából jött-e, és ilyenkor egy osztály le-, majd visszavétele kikényszeríti az újraszámolást.

A második réteg egy őr, ami akkor is kiment, ha az első nem lett volna elég: fél másodperccel a megjelenés után megnézi, van-e olyan szekció, ami a nézetben van, mégis átlátszó. Ha talál ilyet, végleg lekapcsolja az animációt. Inkább legyen a lap animáció nélkül olvasható, mint szépen üres.

A valódi tanulság

Nem a bfcache a hibás, és nem is a CSS. A hiba szerkezeti: olyan animációt írtam, aminek a kezdőállapota elrejti a tartalmat. Minden ilyen animációnál igaz, hogy ha bármilyen okból nem indul el, akkor a tartalom nem részlegesen sérül, hanem eltűnik.

Ezért van azóta padló az animáción: a kezdőérték nem nulla, hanem valamivel a fölött. Az effekt így is látszik, a legrosszabb eset viszont már nem üres lap, hanem egy halványabb szekció. Ez nem utólagos mentés, hanem elvi védelem — a hibaállapotnak olvashatónak kell maradnia.

Ugyanez az elv szólal meg máshol is: egy hiba akkor elfogadható, ha látszik rajta, hogy hiba — a néma törés a veszélyes. Erről szól a deploy-csapdákról írt darab is, ahol a parancs zölden fut le, és mégis rossz az eredmény.

Kérdések a témáról

Mi az a bfcache, és miért okoz gondot animációnál?

A vissza gombra a böngésző nem tölti újra a lapot, hanem memóriából állítja helyre, teljes állapotával együtt. Ez gyors, viszont a görgetéshez kötött animációk idővonala nem feltétlenül számolódik újra — az elemek a kezdő állapotukon maradhatnak. Ha az a kezdőállapot átlátszó, a tartalom helyén üresség marad.

Miért veszélyes az opacity: 0 kezdőérték?

Mert a hibaállapota nem részleges, hanem teljes: nem halványabb lesz a szöveg, hanem nincs ott. Ha az animáció bármilyen okból nem indul el, a látogató üres lapot lát, miközben a tartalom a dokumentumban végig ott van. Ezért érdemes a kezdőértéket nullánál magasabbra tenni.

Hogyan lehet tesztelni ezt a hibát?

Nem újratöltéssel, mert az elfedi. Le kell görgetni a lap aljára, elnavigálni egy másik oldalra, majd a böngésző vissza gombjával visszalépni. A hiba a lap alsó felén a legláthatóbb, mert oda görgetve szokás továbbmenni.

Megéri egyáltalán a CSS-alapú megoldás?

Igen, mert nincs szkript a fő szálon és nincs elem-megfigyelés. De csak akkor, ha a hibaállapot olvasható marad. Egy animáció, aminek az elromlása üres lapot ad, nem díszítés, hanem kockázat.

← Vissza a Műhelyhez