Evita el rebote de iOS sin desactivar la capacidad de desplazamiento

Estoy intentando implementar una solución para evitar el efecto de rebote de iOS en Safari para iOS cuando el contenido de una página web es mayor que el de la vista.

La página en la que estoy trabajando es bastante específica en su estructura, y es muy similar a esta página http://new.salt.ch/

  • La estructura básica está basada en bootstrap.
  • Tiene una barra de navigation fija en la parte superior.
  • Tiene una presentación de background en pantalla completa.
  • La presentación de diapositivas tiene una superposition que se fija en la parte inferior de la window gráfica.
  • Hay un elemento de pie de página que carga fuera del canvas y solo se ve al desplazar el contenido.
  • El contenido se desplaza detrás de la barra de navigation.
  • El contenido consiste en un título que se coloca 20px debajo de la barra de navigation y una serie de botones que se ubican 20px por encima de la window gráfica.
  • Cuando se desplaza, los botones y el título se desplazan por la pantalla para mostrar el pie de página.

El problema que estoy teniendo es el mismo que el problema en la página http://new.salt.ch/ en que cuando se desplaza hacia arriba, se obtiene un efecto de rebote en la parte inferior de la pantalla que revela el background y la superposition.

He intentado varias soluciones, incluyendo iNoBounce.js, Nonbounce.js y algunas otras sugerencias que he encontrado en SO.

Siempre tengo el mismo problema … cuando bash desactivar el rebote, todo el desplazamiento se deshabilita. Supongo que esto se debe a que el contenido (que no sea el pie de página) siempre es lo suficientemente grande como para que el desplazamiento no sea necesario, por lo que el desplazamiento se deshabilita y el pie de página ya no es accesible en el desplazamiento.

Este código debe detener el rebote, ya que es la label HTML que rebota

html { height : 100%; overflow: hidden; } body { height : 100%; overflow: auto; } 

Si estoy interpretando su pregunta correctamente, hemos estado teniendo el mismo problema durante años desarrollando aplicaciones web mobilees multiplataforma, intentando que todas las diferentes funciones de desplazamiento propias funcionen correctamente en cada dispositivo: Apple iOS, Google Android, Windows Teléfono, computadora portátil Chrome, computadora portátil Safari, IE y computadora portátil Edge.

jQuery Mobile continúa intentando solucionar esto dentro de los límites de su marco de trabajo, pero es un montón de whack-a-mole, con las actualizaciones constantes de cada fabricante de dispositivos / fabricante de SO.

Sí, tenemos soluciones para cada dispositivo mobile individual. Y hemos probado, pero no consideramos seriamente el desarrollo de frameworks de pagination selectivos de dispositivos para cada dispositivo, que requieren que detectemos cada dispositivo y presentemos un marco ligeramente diferente para cada uno. Insanely mala idea con básicamente mantener al less 3 y realmente hasta una docena de versiones diferentes de tu código.

SOLUCIÓN: Hemos tenido más suerte simplemente poniendo su encabezado y pie de página persistentes en la parte superior de su marco de página. Aquí está la solución general que usa styles en línea para simplificar:

 <html> <head> <title>Fixed Header and Footer on All Mobile Web Apps</title> <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0" /> <style> html, body { height:100%; width:100%; } </style> </head> </body> <div style="position: fixed; height:100%; width:100%; top:0; left:0;"> <div style="height:calc(100% - 1px); width:100%; margin-top: 60px; z-index: 1; overflow-y: scroll; -webkit-overflow-scrolling: touch;"> [Body Content That Can Scroll if it extends beyond screen...] </div> <div style="position: absolute; top:0; left:0; width:100%; height: 60px; background:#dddddd; z-index:10;"> [Header Content...] </div> <div style="position: absolute; bottom:0; left:0; width:100%; height: 40px; background:#cccccc; z-index:11;"> [Footer Content...] </div> </div> </body> </html> 

Entonces, el cuerpo podría ser cualquier set de páginas jQuery Mobile. De hecho, en teoría, el cuerpo podría ser casi cualquier contenido de cualquier marco.

Nota especial, la línea con altura: calc (100% – 1px); es fundamental para la magia.

Las aparentemente infinitas combinaciones o permutaciones de este tema casi se han convertido en una cruzada para nosotros a lo largo de los años, tratando de encontrar la solución más pura, más sencilla y universalmente compatible. Entonces, después de dedicar un número embarazoso de horas hombre a este tema, esta no es solo nuestra mejor solución, sino que también es el ÚNICO enfoque universalmente compatible que hemos encontrado que también te permite seguir con solo una base de código singular. Se ha probado con éxito en las últimas versiones de iOS, Windows Phone, Android, laptop Chrome, laptop Safari, PhoneGap, laptop Firefox, IE 9-11 y Windows Edge.

TAGS: aplicación mobile, aplicación web, encabezado fijo, pie de página fijo, encabezado persistente, pie de página persistente, problema de desplazamiento, rebote de desplazamiento de iOS, rebote de desplazamiento de Chrome, rebote de desplazamiento de Android, problema de desplazamiento de webkit, desplazamiento táctil de webkit

Revisé algunas respuestas en SO y las cosas parecían sombrías hasta tropezar con este código.

 html { position: fixed; height: 100%; overflow: hidden; } body { width: 100vw; height: 100vh; overflow-y: scroll; overflow-x: hidden; -webkit-overflow-scrolling: touch; } 

Las declaraciones de estilo para el body se pueden poner en cualquier elemento que desee tener la capacidad de desplazarse. También puede alterar overflow-x y overflow-y según sea necesario. Personalmente, necesitaba que NO se desplazara hacia los lados, así que lo declaré como tal.

actualización 15 de septiembre de 2017: Tuve que usar esta corrección para otro proyecto y pude hacer sin estas declaraciones position: fixed y height: 100%; en el selector html . YMMV

Logré resolver la mayoría de los problemas que soportan el overflow: auto y overflow: scroll en el Safari mobile:

  • sin colgar la vista de desplazamiento después de tocar al principio de la list, luego moverse hacia abajo y luego hacia arriba (Safari mobile ejecuta su comportamiento de rebote pnetworkingeterminado para toda la página en ese caso)
  • Soporte para encabezado fijo / barra de acción en la parte superior sin superposition fea de él por una barra de desplazamiento
 window.addEventListener('DOMContentLoaded', function () { var atTop = true; var atBottom = false; var body = document.getElementById('fixedBody'); body.addEventListener('touchmove', function(event){ event.preventDefault(); }); body.addEventListener('touchstart', function(event){ event.preventDefault(); }); body.addEventListener('touchend', function(event){ event.preventDefault(); }); var scrollingDiv = document.getElementById('scrollDiv'); if (scrollingDiv.scrollHeight <= scrollingDiv.clientHeight) { atBottom = true; } scrollingDiv.addEventListener('scroll', function(event){ if (event.target.scrollTop === 0) { atTop = true; } else { atTop = false; } if (event.target.scrollHeight - event.target.scrollTop === event.target.clientHeight) { atBottom = true; } else { atBottom = false; } }); var lastY = 0; var topLock = false; var bottomLock = false; scrollingDiv.addEventListener('touchmove', function(event){ event.stopPropagation(); var currentY = event.touches[0].clientY; if (currentY > lastY) { // moved down if (atTop) { event.preventDefault(); topLock = true; } if (bottomLock) { bottomLock = false; // TODO: Emulate finger remove and touch again here } } else if(currentY < lastY){ // moved top if (atBottom) { event.preventDefault(); bottomLock = true; } if (topLock) { topLock = false; // TODO: Emulate finger remove and touch again here } } lastY = currentY; }); scrollingDiv.addEventListener('touchstart', function(event){ lastY = event.touches[0].clientY; event.stopPropagation(); }); scrollingDiv.addEventListener('touchend', function(event){ event.stopPropagation(); }); }); 
 <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> </head> <body id="fixedBody" style="overflow: hidden;"> <div style="position: fixed; height: 64px; width:100%; top:0; left:0; background-color: green; z-index: 1;"> Header </div> <div id="scrollDiv" style="position: absolute; width: 100%; top: 64px; bottom: 0px; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; background-color: white;"> <div style="height: 150px; background-color: blue;"> First </div> <div style="height: 150px; background-color: networking;"> Second </div> <div style="height: 150px; background-color: green;"> Third </div> <div style="height: 150px; background-color: black;"> Another </div> </div> </body> </html> 

Utilicé iNoBounce https://github.com/lazd/iNoBounce y funciona perfectamente.

Si necesita permitir el desplazamiento horizontal también, hay una request de extracción de santi6291 en https://github.com/lazd/iNoBounce/pull/36 que corrige que