Adicto profesional a Internet • Entusiasta de los juegos • Creador de tecnología
Adicto profesional a Internet • Entusiasta de los juegos • Creador de tecnología

Seis cosas que aprendí sobre el desplazamiento con rebote de iOS Safari

¡Para solucionar un problema de desplazamiento en Safari en iOS, me vi obligado a crear mi propia página de prueba sencilla!
Esta página ha sido traducida del inglés por mis altamente motivados pasantes de IA para su comodidad. Aún están aprendiendo, por lo que es posible que se hayan pasado por alto algunos errores. Para obtener la información más precisa, consulte la versión en inglés.
Hogar Blog Seis cosas que aprendí sobre el desplazamiento con rebote de iOS Safari

Tenga en cuenta que esta entrada del blog se publicó en junio de 2015, por lo que, dependiendo de cuándo la lea, algunas partes podrían estar desactualizadas. Lamentablemente, no siempre puedo mantener estas publicaciones completamente actualizadas para garantizar que la información siga siendo precisa.

Para solucionar un reciente problema de desplazamiento en Safari en iOS, tuve que crear mi propia página de prueba simple y luego aplicar toda la información y las combinaciones que pude encontrar en Internet para intentar resolver el problema.

A continuación, se presenta un breve resumen de lo que descubrí durante este proceso.

Mi página de prueba

Mi página de prueba era bastante básica. Consistía en datos simulados en un div estático para representar la "página", junto con un div fijo para representar un "menú" superpuesto sobre la página, así.

Una captura de pantalla de un menú lateral en HTML abierto en iOS Safari

El código fuente completo de la página se puede encontrar al final de esta entrada del blog.

Comprender el comportamiento predeterminado

Lo primero que hice fue tratar de entender el comportamiento por defecto de Safari en iOS. Lo más notable fue que, al desplazarte hasta el fondo del menú, el cuerpo de la página mostraba un efecto de banda elástica, una característica integrada de Safari.

una captura de pantalla animada del molesto efecto de la banda elástica en Safari de iOS en la parte inferior de la página

Lo mismo pasó al desplazarse hasta la parte superior del menú.

una captura de pantalla animada del molesto efecto de rebote de iOS Safari en la parte superior de la página

Sin embargo, el primer problema que noté fue que, si te desplazas de forma continua hasta la parte superior o inferior, Safari empieza a mostrar fallos de renderizado tanto en la página de fondo como en el menú.

No estoy seguro de por qué, pero sospecho que tiene algo que ver con la función de selección por banda.

una captura de pantalla animada del problema de Safari en iOS con fallos, en la parte inferior de la página

Entendiendo qué hace la regla CSS "-webkit-overflow-scrolling"

Lo siguiente que hice fue aplicar la regla CSS -webkit-overflow-scrolling al menú, lo cual permite el desplazamiento con inercia.

Como se muestra en la imagen de abajo, el desplazamiento continúa incluso después de deslizar con el dedo.

Mostrando el problema de desplazamiento por inercia en iOS Safari

Pero también añade un efecto de banda elástica al desplazarte hasta la parte superior o inferior, como se muestra a continuación.

Mostrando el problema de desplazamiento por inercia en iOS Safari con el efecto de banda elástica

El usuario debe esperar a que termine el efecto de rebote.

Durante mis pruebas, también observé que, mientras el efecto de banda elástica está en curso, el usuario no puede cambiar el enfoque a otro elemento hasta que la animación haya terminado por completo.

En el ejemplo a continuación, primero desplazo la página de fondo y luego intento desplazar el menú rápidamente, pero termino desplazando la página de fondo.

mostrando que la página de fondo se desplaza en iOS Safari

Sin embargo, si espero un momento a que termine el efecto, entonces ya puedo empezar a desplazarme por el menú.

mostrando la espera hasta que termine el efecto de banda elástica en iOS Safari

Cómo evitar que la página de fondo se desplace

Durante mis pruebas, también observé que, mientras el efecto de rebote está en curso, el usuario no puede cambiar el foco a otro elemento hasta que la animación haya terminado por completo.

A partir de esta respuesta de Stack Overflow, puedes asegurarte de que los elementos con disable-scrolling no realicen su acción de desplazamiento por defecto cuando se dispare el 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(); } };

Y luego aplica la clase disable-scrolling al div de la página:

<div class="page disable-scrolling">

Esto funciona más o menos, pero pruebas más exhaustivas muestran que la página de fondo aún puede desplazarse a veces cuando llegas a la parte superior o inferior del menú.

mostrando que el fondo aún se está desplazando

Cómo evitar que el fondo se desplace en exceso

Al aplicar esta solución, es posible evitar el desbordamiento. Esto significa que cuando un elemento llega a la parte superior o inferior de su recorrido, el desplazamiento no continúa hacia el cuerpo de la página.

Como resultado, se evita el desplazamiento del cuerpo, lo que también impide que ocurra el efecto de rebote.

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

Lo que hace este fragmento de JavaScript es evitar que el elemento alcance la parte superior o la inferior, manteniéndolo a solo 1 píxel de distancia.

Si la posición de desplazamiento nunca llega a la parte superior ni a la inferior, el desbordamiento no puede ocurrir.

demostración de cómo evitar el desplazamiento excesivo al no llegar nunca a la parte superior ni a la inferior

Cómo evitar el desplazamiento excesivo hacia la página de fondo

Si quieres eliminar el efecto de banda elástica del menú, ya sea por motivos estéticos o porque, como en mi caso, causó problemas de renderizado adicionales, simplemente elimina la regla CSS -webkit-overflow-scrolling.

Sin embargo, como puedes ver a continuación, también se pierde la inercia del desplazamiento suave.

Demostración completa para evitar el efecto de rebote en iOS Safari

Código fuente de toda la página

Aquí está el código fuente completo 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>

Escrito por Special Agent Squeaky. Publicado por primera vez el 10 de junio de 2015. Última actualización: 10 de junio de 2015.

📺 ¡Mira el video más reciente de Squeaky!

Cómo agregar subtítulos simples en tiempo real a tu transmisión en vivo