Professionell internetberoende • Spelentusiast • Teknikskapare
Professionell internetberoende • Spelentusiast • Teknikskapare

Sex saker jag lärde mig om iOS Safari:s gummibandsrullning

För att åtgärda ett problem med scrollningen i Safari på iOS blev jag tvungen att skapa min egen enkla testsida!
Den här sidan har översatts från engelska av mina mycket motiverade AI-praktikanter för din bekvämlighet. De lär sig fortfarande, så några misstag kan ha smugit sig igenom. För den mest korrekta informationen, vänligen se den engelska versionen.
Hem Blogg Sex saker jag lärde mig om iOS Safari:s gummibandsrullning

Observera att detta blogginlägg publicerades i juni 2015, så beroende på när du läser det kan vissa delar vara inaktuella. Tyvärr kan jag inte alltid hålla dessa inlägg helt uppdaterade för att säkerställa att informationen förblir korrekt.

För att åtgärda ett nyligen uppkommet problem med rullningen i Safari på iOS var jag tvungen att skapa min egen enkla testsida och sedan använda all information och de kombinationer jag kunde hitta på nätet för att försöka lösa problemet.

Nedan följer en kort översikt över vad jag upptäckte under denna process.

Min testsida

Min testsida var ganska grundläggande. Den bestod av mockdata i en statisk div för att representera 'sidan', tillsammans med en fixerad div som representerar en överlagrad 'meny' ovanför sidan, så här.

En skärmdump av en öppen HTML-sidomeny i iOS Safari

Den fullständiga källkoden till sidan finns längst ner i detta blogginlägg.

Förstå standardbeteendet

Det första jag gjorde var att försöka förstå Safaris standardbeteende på iOS. Det mest slående var att när man rullade ända ner till botten av menyn visade sidans kropp en gummibandseffekt – en hårdkodad funktion i Safari.

en animerad skärmdump av den problematiska gummibands-effekten i iOS Safari längst ner på sidan

Samma sak hände när man scrollade till längst upp i menyn.

en animerad skärmdump av den problematiska gummibandseffekten i iOS Safari längst upp på sidan

Men det första problemet jag märkte var att om du kontinuerligt scrollar till toppen eller botten så uppstår renderingsfel på både bakgrundssidan och i menyn i Safari.

Jag vet inte riktigt varför, men jag misstänker att det har något att göra med gummibandsfunktionen.

en animerad skärmdump av det glitchiga iOS Safari-problemet längst ner på sidan

Förstå vad CSS-regeln "-webkit-overflow-scrolling" gör

Nästa sak jag gjorde var att tillämpa CSS-regeln -webkit-overflow-scrolling på menyn, som möjliggör momentum-baserad scrollning.

Som bilden nedan visar fortsätter scrollningen även efter att jag sveper med mitt finger.

visar problemet med momentumbaserad rullning på iOS Safari

Men det ger också en gummibandseffekt när du scrollar till toppen eller botten, som visas nedan.

visar problemet med momentumbaserad rullning på iOS Safari med gummibandseffekten

Användaren måste vänta tills gummibandseffekten avslutas.

Under min testning märkte jag också att medan gummibandseffekten pågår kan användaren inte flytta fokus till ett annat element förrän animationen har slutförts helt.

I nedanstående exempel rullar jag först bakgrundssidan och försöker sedan snabbt rulla i menyn, men jag fortsätter ändå att rulla bakgrundssidan.

visar att bakgrundssidan har rullats på iOS Safari

Om jag väntar ett ögonblick tills effekten är färdig kan jag sedan börja scrolla i menyn.

visar väntan tills gummibandseffekten avslutas iOS Safari

Så här förhindrar du att bakgrundssidan scrollar

Under min testning märkte jag också att medan gummibandseffekten pågår kan användaren inte flytta fokus till ett annat element förrän animationen är helt färdig.

Baserat på detta svar från Stack Overflow kan du säkerställa att element med disable-scrolling inte utför sin standardrullningsåtgärd när touchmove-händelsen 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(); } };

Och applicera sedan klassen disable-scrolling på sidans div-elementet:

<div class="page disable-scrolling">

Det här fungerar till viss del, men mer omfattande tester visar att bakgrundssidan fortfarande ibland kan scrolla när du når menyns översta eller nedersta del.

visar att bakgrunden fortfarande scrollas

Hur du förhindrar att sidan scrollar till bakgrundssidan

Genom att tillämpa denna fix går det att förhindra överscrollning. Det innebär att när ett element scrollas till sin absoluta topp eller botten, fortsätter inte scrollningen in i sidans innehåll.

Som ett resultat förhindras sidan från att scrolla, vilket också förhindrar att gummibandseffekten uppstå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"));

Det här JavaScript-snippetet gör så att elementet aldrig når toppen eller botten helt och hållet, utan hålls endast 1 pixel från både toppen och botten.

Om scrollpositionen aldrig når den absoluta toppen eller botten, kan överscrollning aldrig uppstå.

demo som förhindrar överscrollning genom att aldrig nå toppen eller botten

Så här förhindrar du överscroll till bakgrundssidan

Om du vill ta bort gummibandseffekten i menyn – antingen av estetiska skäl eller eftersom, som i mitt fall, den orsakade ytterligare renderingfel – ta helt enkelt bort CSS-regeln -webkit-overflow-scrolling.

Men, som du kan se nedan, förlorar du också den smidiga rullningen.

fullständig demo för att förhindra gummibandseffekten i iOS Safari

Hela sidans källkod

Här är hela sidans källkod.

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

Skriven av Special Agent Squeaky. Först publicerad 2015-06-10. Senast uppdaterad 2015-06-10.

📺 Se den senaste videon från Squeaky!

Så här lägger du till enkla realtidsundertexter till din liveström.