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.
- 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.