Addicte professional a Internet • Entusiasta dels videojocs • Creador de tecnologia
Addicte professional a Internet • Entusiasta dels videojocs • Creador de tecnologia

Sis coses que vaig aprendre sobre el desplaçament elàstic de Safari en iOS

Per arreglar un problema de desplaçament a Safari en iOS, em va tocar crear la meva pròpia pàgina de prova senzilla!
Aquesta pàgina ha estat traduïda de l'anglès pels meus becaris d'IA, altament motivats, per a la vostra comoditat. Encara estan aprenent, així que és possible que s'hagin escapat alguns errors. Per obtenir la informació més precisa, consulteu la versió anglesa.
Inici Bloc Sis coses que vaig aprendre sobre el desplaçament elàstic de Safari en iOS

Aquesta entrada es va publicar el juny de 2015; potser alguna informació ja hagi quedat enrere. No sempre puc revisar-ho tot, però segueix sent interessant!

Per resoldre un problema recent de desplaçament a Safari en iOS, vaig haver de crear la meva pròpia pàgina de proves senzilla i, després, aplicar tota la informació i les combinacions que vaig poder trobar a Internet per intentar resoldre el problema.

A continuació, trobaràs un breu resum de tot el que he descobert durant aquest procés.

La meva pàgina de proves

La meva pàgina de proves era bastant senzilla. Consistia en dades simulades en un element div estàtic per representar la 'pàgina', i, a més, un div fix que representava un 'menú' superposat sobre la pàgina, així.

Una captura de pantalla d'un menú lateral HTML obert en Safari d'iOS

El codi font complet de la pàgina es pot trobar al final d'aquest article del blog.

Comprendre el comportament per defecte

La primera cosa que vaig fer va ser intentar entendre el comportament per defecte de Safari en iOS. L'observació més destacada va ser que, quan desplacaves fins al final del menú, el cos de la pàgina mostrava un efecte d'estirament elàstic — una característica codificada directament a Safari.

una captura de pantalla animada de l'efecte de goma problemàtic de Safari d'iOS a la part inferior de la pàgina

Va passar el mateix quan vaig fer scroll fins a la part superior del menú.

una captura de pantalla animada de l'efecte de goma problemàtic a Safari d'iOS a la part superior de la pàgina

Tanmateix, el primer problema que vaig notar va ser que si desplacaves contínuament fins al cim o al fons, Safari començava a mostrar fallades de renderització tant a la pàgina de fons com al menú.

No estic segur de per què, però sospito que té alguna cosa a veure amb l'efecte de goma elàstica.

una captura de pantalla animada del problema de Safari en iOS que falla, a la part inferior de la pàgina

Comprendre què fa la propietat CSS "-webkit-overflow-scrolling"

El següent pas que vaig fer va ser aplicar la regla CSS -webkit-overflow-scrolling al menú, que permet el desplaçament amb inèrcia.

Com es veu a la imatge de més avall, el desplaçament continua fins i tot després de desplaçar-me amb el dit.

mostrant el problema de desplaçament per inèrcia a iOS Safari

Però també s'afegeix un efecte de goma quan s'arriba a la part superior o inferior, com es mostra a continuació.

mostrant el problema de desplaçament basat en l'inèrcia a Safari d'iOS amb l'efecte de goma

L'usuari ha d'esperar fins que s'acabi l'efecte de goma elàstica.

Durant les meves proves, també vaig observar que, mentre l'efecte elàstic està en curs, l'usuari no pot canviar el focus a un altre element fins que l'animació s'hagi completada.

En l’exemple següent, primer desplaço la pàgina de fons i, a continuació, intento desplaçar ràpidament el menú, però acabo desplaçant la pàgina de fons en lloc d’això.

mostrant que la pàgina de fons es desplaça en iOS Safari

Tanmateix, si espero un moment que l’efecte acabi, ja podré començar a desplaçar-me pel menú.

mostrant l'espera perquè acabi l'efecte elàstic a Safari d'iOS

Com evitar que la pàgina en segon pla faci scroll

Durant les meves proves, també vaig observar que, mentre l'efecte de goma elàstica està en curs, l'usuari no pot desviar el focus cap a un altre element fins que l'animació estigui completament finalitzada.

Basat en aquesta resposta de Stack Overflow, podeu assegurar que els elements amb disable-scrolling no executin la seva acció de desplaçament per defecte quan s'activa l'esdeveniment 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(); } };

I després aplica la classe disable-scrolling al div de la pàgina:

<div class="page disable-scrolling">

Aquest tipus funciona, però proves més extenses demostren que la pàgina de fons encara pot desplaçar-se de tant en tant quan arribes a la part superior o inferior del menú.

mostrant que el fons encara s'està desplaçant

Com evitar que la pàgina en segon pla es desplaci.

Aplicant aquesta solució, és possible evitar el desbordament. Això implica que quan un element arriba a la part superior o inferior, el desplaçament no continua dins del cos de la pàgina.

Com a resultat, s'evita el desplaçament del cos de la pàgina, i això també evita que aparegui l'efecte de goma.

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

Aquest fragment de JavaScript evita que l'element arribi mai a la part superior ni a la part inferior, mantenint-lo a només 1 píxel de distància.

Si la posició de desplaçament mai no arriba al límit superior ni al límit inferior, l'excés de desplaçament no pot passar.

Demostració de la prevenció de l'overscroll evitant arribar mai al començament ni al final

Com evitar el desplaçament excessiu cap a la pàgina en segon pla

Si vols eliminar l'efecte de goma del menú, sigui per motius estètics o perquè, com en el meu cas, va provocar problemes addicionals de renderització, elimina simplement la regla CSS -webkit-overflow-scrolling.

No obstant això, com podeu veure a continuació, també perdeu la inèrcia del desplaçament suau.

Demostració completa per evitar l’efecte d’estirament (rubberbanding) a iOS Safari

Codi font de tota la pàgina

Aquí teniu el codi font complet de la pàgina.

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

Escrit per Special Agent Squeaky. Publicat per primera vegada el 10-06-2015. Última actualització el 10-06-2015.

📺 Mira l'últim vídeo de Squeaky!

Com afegir subtítols en temps real simples a la teva transmissió en directe