Profesjonell internettavhengig • Spillentusiast • Teknologiskaper
Profesjonell internettavhengig • Spillentusiast • Teknologiskaper

Seks ting jeg lærte om iOS Safaris gummibåndseffekten

For å fikse et rulleproblem i Safari på iOS, måtte jeg lage min egen enkle testside!
Denne siden er oversatt fra engelsk av mine svært motiverte AI-praktikanter for enkelhets skyld. De lærer fortsatt, så noen feil kan ha sneket seg gjennom. For den mest nøyaktige informasjonen, vennligst se den engelske versjonen.
Hjem Blogg Seks ting jeg lærte om iOS Safaris gummibåndseffekten

Vær oppmerksom på at dette blogginnlegget ble publisert i juni 2015, så avhengig av når du leser det, kan enkelte deler være utdaterte. Dessverre kan jeg ikke alltid holde disse innleggene helt oppdaterte for å sikre at informasjonen forblir nøyaktig.

For å fikse et nylig rulleproblem i Safari på iOS, ble jeg nødt til å lage min egen enkle testside og deretter bruke all informasjon og alle kombinasjonene jeg kunne finne på nettet for å prøve å løse problemet.

Nedenfor følger en kort oversikt over hva jeg har funnet ut i løpet av denne prosessen.

Min testside

Min testside var ganske enkel. Den besto av mock-data i en statisk div for å representere «siden», sammen med en fast div for å representere en overlagt «meny» over siden, slik.

Et skjermbilde av en åpen HTML-side-meny i iOS Safari

Den komplette kildekoden til siden finner du nederst i dette blogginnlegget.

Forstå standardoppførsel

Det første jeg gjorde var å prøve å forstå standardoppførselen i Safari på iOS. Den mest bemerkelsesverdige observasjonen var at når du scrollet helt ned til bunnen av menyen, viste sidens innhold en "gummibånd-effekt" - en innebygd funksjon i Safari.

et animert skjermbilde av den problematiske gummibånd-effekten iOS Safari nederst på siden

Det samme skjedde da jeg scrollet helt til toppen av menyen.

et animert skjermbilde av den problematiske gummibåndeffekten i iOS Safari øverst på siden

Imidlertid var det første problemet jeg la merke til at hvis du ruller kontinuerlig helt til toppen eller bunnen, begynner Safari å vise renderingsfeil i både bakgrunnssiden og menyen.

Jeg er ikke sikker på hvorfor, men jeg mistenker at det har noe å gjøre med gummibåndfunksjonen.

et animert skjermbilde som viser problemet med iOS Safari som glitcher nederst på siden

Forstå hva CSS-regelen "-webkit-overflow-scrolling" gjør

Det neste jeg gjorde var å bruke CSS-regelen -webkit-overflow-scrolling på menyen, som gir momentumbasert scrolling.

Som vist i bildet nedenfor, fortsetter rullingen selv om jeg sveiper med fingeren.

viser problemet med momentumbasert rulling på iOS Safari

Men det gir også en gummibåndseffekt når du ruller helt til toppen eller bunnen, som vist nedenfor.

viser et momentumbasert rulleproblem i iOS Safari med gummibåndseffekten

Brukeren må vente til gummibåndseffekten er ferdig.

Under testingen jeg gjennomførte la jeg også merke til at mens gummibåndseffekten pågår, kan brukeren ikke flytte fokus til et annet element før animasjonen er fullført.

I eksemplet nedenfor scroller jeg først på bakgrunnssiden og prøver deretter raskt å scrolle i menyen, men ender opp med å fortsette å scrolle på bakgrunnssiden i stedet.

viser at bakgrunnssiden er rullet på iOS Safari

Men hvis jeg venter et øyeblikk til effekten er ferdig, kan jeg deretter begynne å bla i menyen.

viser ventetiden før den elastiske effekten i ios safari er ferdig

Slik hindrer du at bakgrunnssiden ruller

Under testingen min la jeg også merke til at mens gummibåndseffekten pågår, kan brukeren ikke flytte fokus til et annet element før animasjonen er helt ferdig.

Basert på dette svaret fra Stack Overflow, kan du sikre at elementer med disable-scrolling ikke utfører deres standard rulleeffekt når touchmove-hendelsen utløses.

document.ontouchmove = function(event) { var isTouchMoveAllowed = true, target = event.target; while (target !== null) { if (target.classList && target.classList.contains('disable-scrolling')) { isTouchMoveAllowed = false; break; } target = target.parentNode; } if (!isTouchMoveAllowed) { event.preventDefault(); } };

Og deretter bruker du klassen disable-scrolling på sidens div:

<div class="page disable-scrolling">

Dette fungerer greit, men mer omfattende tester viser at bakgrunnssiden fortsatt noen ganger kan rulle når du når øverste eller nederste del av menyen.

viser at bakgrunnen fortsatt blir rullet

Hvordan forhindre at bakgrunnssiden scroller for mye

Ved å bruke denne løsningen, blir det mulig å forhindre «overscroll». Dette betyr at når et element rulles helt til toppen eller bunnen, fortsetter ikke rulningen inn i body-delen.

Som et resultat hindres siden fra å skrolle, noe som også hindrer at gummibåndseffekten oppstår.

function removeIOSRubberEffect(element) { element.addEventListener("touchstart", function() { var top = element.scrollTop, totalScroll = element.scrollHeight, currentScroll = top + element.offsetHeight; if (top === 0) { element.scrollTop = 1; } else if (currentScroll === totalScroll) { element.scrollTop = top - 1; } }); } removeIOSRubberEffect(document.querySelector(".scrollable"));

Hva denne JavaScript-kodesnutten gjør, er å forhindre at elementet når helt opp til toppen eller bunnen ved å holde det bare 1 piksel unna.

Hvis rulleposisjonen aldri når den absolutte toppen eller bunnen, kan ikke overscroll forekomme.

demonstrasjon av å forhindre overscroll ved aldri å gå helt til toppen eller bunnen

Slik hindrer du overscroll til bakgrunnssiden

Hvis du vil fjerne gummibånd-effekten fra menyen – enten av estetiske årsaker eller fordi det, som i mitt tilfelle, førte til ekstra gjengivelsesproblemer – fjern ganske enkelt CSS-regelen -webkit-overflow-scrolling.

Men som du ser nedenfor, mister du også det jevne rullemomentet.

fullstendig demo for å forhindre rubberbanding på iOS Safari

Hele sidens kildekode

Her er hele kildekoden til siden.

<!-- License MIT, Author Special Agent Squeaky (specialagentsqueaky.com) --> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <style> .page{ font-size: 24px; overflow: scroll; } .menu{ position: fixed; top: 0; bottom: 0; left: 0; width: 80%; background: gray; z-index: 1; font-size: 10px; overflow: scroll; /* uncomment to get smooth momentum scroll, but also a rubber band effect */ /*-webkit-overflow-scrolling: touch;*/ } .menu-item{ padding: 10px; background: darkgray; font-size: 24px; } </style> </head> <body> <div class="menu scrollable"> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> <div class="menu-item">hello world</div> </div> <div class="page disable-scrolling"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. </div> <script> document.ontouchmove = function(event) { var isTouchMoveAllowed = true, target = event.target; while (target !== null) { if (target.classList && target.classList.contains('disable-scrolling')) { isTouchMoveAllowed = false; break; } target = target.parentNode; } if (!isTouchMoveAllowed) { event.preventDefault(); } }; function removeIOSRubberEffect(element) { element.addEventListener("touchstart", function() { var top = element.scrollTop, totalScroll = element.scrollHeight, currentScroll = top + element.offsetHeight; if (top === 0) { element.scrollTop = 1; } else if (currentScroll === totalScroll) { element.scrollTop = top - 1; } }); } removeIOSRubberEffect(document.querySelector(".scrollable")); </script> </body> </html>

Skrevet av Special Agent Squeaky. Først publisert 10.06.2015. Sist oppdatert 10.06.2015.

📺 Se Squeaky sin nyeste video!

Slik legger du til enkle sanntidsundertekster i direktesendingen din.