Dipendente professionista di Internet • Appassionato di giochi • Creatore di tecnologia
Dipendente professionista di Internet • Appassionato di giochi • Creatore di tecnologia

Sei cose che ho imparato sullo scorrimento elastico di Safari su iOS

Per risolvere un problema di scorrimento in Safari su iOS, sono stato costretto a creare una mia semplice pagina di prova!
Questa pagina è stata tradotta dall'inglese dai miei stagisti di intelligenza artificiale, altamente motivati, per vostra comodità. Stanno ancora imparando, quindi potrebbero esserci degli errori. Per informazioni più accurate, consultate la versione inglese.
Casa Blog Sei cose che ho imparato sullo scorrimento elastico di Safari su iOS

Si prega di notare che questo post del blog è stato pubblicato a giugno 2015, quindi, a seconda di quando lo si legge, alcune parti potrebbero non essere aggiornate. Purtroppo, non posso sempre mantenere questi post completamente aggiornati per garantire che le informazioni rimangano accurate.

Per risolvere un recente problema di scorrimento in Safari su iOS, sono stato costretto a creare una semplice pagina di test e, successivamente, a mettere in pratica tutte le informazioni e le combinazioni che ho trovato sul web per cercare di risolvere il problema.

Di seguito trovi una breve panoramica di ciò che ho scoperto durante questo processo.

La mia pagina di prova

La mia pagina di prova era abbastanza semplice. Era costituita da dati simulati in un div statico per rappresentare la "pagina", insieme a un div fisso per rappresentare un "menu" sovrapposto alla pagina, così.

Una schermata di un menu laterale HTML aperto su iOS Safari

Il codice sorgente completo della pagina si trova in fondo a questo post del blog.

Capire il comportamento predefinito

La prima cosa che ho fatto è stata cercare di capire il comportamento predefinito di Safari su iOS. L'osservazione più notevole è stata che, quando si scorreva fino in fondo al menu, il corpo della pagina mostrava l'«effetto elastico» — una funzione integrata in Safari.

una schermata animata che mostra l'effetto di rimbalzo problematico di iOS Safari in fondo alla pagina

È successo lo stesso anche quando si è arrivato in cima al menu.

uno screenshot animato del problematico effetto elastico in iOS Safari, in cima alla pagina

Tuttavia, il primo problema che ho notato è che se scorri continuamente fino in cima o fino in fondo, Safari inizia a mostrare problemi di rendering sia sulla pagina di sfondo sia nel menu.

Non sono sicuro del perché, ma sospetto che abbia a che fare con la funzionalità elastica.

una schermata animata del problema glitch di iOS Safari in fondo alla pagina

Capire cosa fa la regola CSS "-webkit-overflow-scrolling"

La prossima cosa che ho fatto è stata applicare la regola CSS -webkit-overflow-scrolling al menu, che consente lo scorrimento basato sull'inerzia.

Come mostrato nell'immagine qui sotto, lo scorrimento continua anche dopo aver effettuato uno swipe con il dito.

mostrando il problema di scorrimento basato sull'inerzia su iOS Safari

Ma aggiunge anche un effetto elastico quando si scorre fino in cima o fino in fondo, come mostrato di seguito.

mostra il problema dello scorrimento basato sul momentum su iOS Safari con l'effetto elastico

L'utente deve aspettare che l'effetto elastico termini

Durante i miei test, ho notato anche che, durante l'effetto elastico in corso, l'utente non può spostare il focus su un altro elemento finché l'animazione non è completamente terminata.

Nell'esempio qui sotto, scorro prima la pagina di sfondo e poi cerco di scorrere rapidamente il menu, ma finisco per continuare a scorrere la pagina di sfondo.

mostrando che la pagina di sfondo è stata scrollata, invece, su iOS Safari

Tuttavia, se aspetto un attimo che l'effetto finisca, posso poi iniziare a scorrere il menù.

mostrando l'attesa che l'effetto di rimbalzo finisca su iOS Safari

Come impedire lo scorrimento della pagina di sfondo

Durante i miei test, ho anche notato che, mentre l'effetto elastico è in corso, l'utente non può spostare il focus su un altro elemento finché l'animazione non è completamente terminata.

Basata su questa risposta di Stack Overflow, puoi assicurarti che gli elementi con disable-scrolling non eseguano l'azione di scorrimento predefinita quando viene attivato l'evento touchmove.

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(); } };

E poi applica la classe disable-scrolling al div della pagina:

<div class="page disable-scrolling">

Questo funziona abbastanza bene, ma test più approfonditi hanno mostrato che la pagina di sfondo può comunque scorrere a volte quando si raggiunge la parte superiore o inferiore del menu.

mostrando che lo sfondo sta ancora scorrendo

Come impedire lo scorrimento della pagina di sfondo

Applicando questa soluzione, è possibile prevenire "overscrolling". Ciò significa che, quando un elemento arriva al punto più alto o al punto più basso dello scorrimento, lo scorrimento non prosegue nel corpo della pagina.

Di conseguenza, viene impedito lo scorrimento del corpo della pagina, e ciò evita anche che si verifichi l'effetto elastico (rubber-band).

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"));

Questo frammento JavaScript impedisce all'elemento di raggiungere mai il bordo superiore o inferiore, mantenendolo a solo 1 pixel di distanza.

Se la posizione di scorrimento non raggiunge mai la parte superiore assoluta né quella inferiore, l'overscroll non può verificarsi.

demo di prevenzione dello scorrimento eccessivo, evitando di arrivare mai in cima né in fondo

Come evitare lo scorrimento eccessivo verso la pagina di sfondo

Se vuoi rimuovere l'effetto elastico dal menu, sia per motivi estetici sia perché, come nel mio caso, ha causato ulteriori problemi di rendering, rimuovi semplicemente la regola CSS -webkit-overflow-scrolling.

Tuttavia, come puoi vedere qui sotto, perdi anche la fluidità dello scorrimento.

Demo completo se si evita l'effetto elastico su iOS Safari

Codice sorgente dell'intera pagina

Ecco il codice sorgente completo della pagina.

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

Scritto da Special Agent Squeaky. Prima pubblicazione 2015-06-10. Ultimo aggiornamento 2015-06-10.

📺 Guarda l'ultimo video di Squeaky!

Come aggiungere sottotitoli in tempo reale semplici al tuo streaming in diretta.