Desplazarse rebotando en sus sitios web

Publicado: 2022-03-10
Resumen rápido ↬ Este artículo describe el efecto del rebote de desplazamiento y cómo funciona en diferentes navegadores web. Contiene revisiones de varias soluciones diferentes que se sugieren en la web que se pueden usar para evitar el rebote de desplazamiento. La propiedad CSS overscroll-behavior , que se implementó en Chrome en diciembre de 2017 y en Firefox en marzo de 2018, también se describe en este artículo. Una buena comprensión de este efecto es muy útil para construir o diseñar cualquier sitio web que tenga elementos fijos.

El rebote de desplazamiento (también denominado a veces "bandas elásticas" o "desplazamiento elástico") se usa a menudo para referirse al efecto que ve cuando se desplaza hasta la parte superior de una página o elemento HTML, o hasta la parte inferior de una página o elemento, en un dispositivo que usa una pantalla táctil o un trackpad, y el espacio vacío se puede ver por un momento antes de que el elemento o la página salte hacia atrás y se alinee con su parte superior/inferior (cuando suelta su toque/dedos). Puede ver que ocurre un efecto similar en el ajuste de desplazamiento de CSS entre elementos.

Sin embargo, este artículo se centra en el rebote de desplazamiento cuando se desplaza hacia la parte superior o inferior de una página web. En otras palabras, cuando el puerto de desplazamiento ha alcanzado su límite de desplazamiento.

Recopilación de datos, la forma poderosa

¿Sabías que CSS se puede utilizar para recopilar estadísticas? De hecho, existe incluso un enfoque de solo CSS para realizar un seguimiento de las interacciones de la interfaz de usuario mediante Google Analytics. Leer un artículo relacionado →

Una buena comprensión del rebote de desplazamiento es muy útil, ya que lo ayudará a decidir cómo crea sus sitios web y cómo desea que se desplace la página.

El rebote de desplazamiento no es deseable si no desea ver elementos fixed en un movimiento de página. Algunos ejemplos incluyen: cuando desea que un encabezado o pie de página se fije en una determinada posición, o si desea que cualquier otro elemento, como un menú, se fije, o si desea que la página se desplace y ajuste en ciertas posiciones en desplazamiento y no desea que se produzca ningún desplazamiento adicional en la parte superior o inferior de la página, lo que confundirá a los visitantes de su sitio web. Este artículo propondrá algunas soluciones a los problemas que se enfrentan cuando se trata de rebotes de desplazamiento en la parte superior o inferior de una página web.

¡Más después del salto! Continúe leyendo a continuación ↓

Mi primer encuentro con el efecto

Noté este efecto por primera vez cuando estaba actualizando un sitio web que construí hace mucho tiempo. Puede ver el sitio web aquí. Se suponía que el pie de página en la parte inferior de la página estaba fijo en su posición en la parte inferior de la página y no se movía en absoluto. Al mismo tiempo, se suponía que podía desplazarse hacia arriba y hacia abajo por los contenidos principales de la página. Idealmente, funcionaría así:

Rebote de desplazamiento en Firefox en macOS
Rebote de desplazamiento en Firefox en macOS. (Vista previa grande)

Actualmente funciona de esta manera en Firefox o en cualquier navegador en un dispositivo sin pantalla táctil o trackpad. Sin embargo, en ese momento, estaba usando Chrome en una MacBook. Estaba desplazándome hasta la parte inferior de la página con un trackpad cuando descubrí que mi sitio web no funcionaba correctamente. Puedes ver lo que pasó aquí:

Rebote de desplazamiento en Chrome en macOS
Desplazarse rebotando en Chrome en macOS. (Vista previa grande)

¡Oh, no! ¡Esto no era lo que se suponía que iba a pasar! Configuré la posición del pie de página para que estuviera en la parte inferior de la página configurando su propiedad de position CSS para que tuviera un valor de fixed . Este también es un buen momento para revisar qué position: fixed; es. De acuerdo con la especificación CSS 2.1, cuando se fija un "cuadro" (en este caso, el pie de página azul oscuro), se "fija con respecto a la ventana gráfica y no se mueve cuando se desplaza". Lo que esto significa es que se suponía que el pie de página no debía moverse cuando se desplaza hacia arriba y hacia abajo en la página. Esto fue lo que me preocupó cuando vi lo que estaba sucediendo en Chrome.

Para que este artículo sea más completo, le mostraré cómo se desplaza la página en Mobile Edge, Mobile Safari y Desktop Safari a continuación. Esto es diferente a lo que sucede al hacer scroll en Firefox y Chrome. Espero que esto le brinde una mejor comprensión de cómo funciona exactamente el mismo código actualmente de diferentes maneras. Actualmente es un desafío desarrollar un desplazamiento que funcione de la misma manera en diferentes navegadores web.

Desplazarse rebotando en Safari en macOS. Se puede ver un efecto similar para Edge y Safari en iOS
Desplazarse rebotando en Safari en macOS. Se puede ver un efecto similar para Edge y Safari en iOS. (Vista previa grande)

Buscando una solución

Uno de mis primeros pensamientos fue que habría una manera fácil y rápida de solucionar este problema en todos los navegadores. Lo que esto significa es que pensé que podría encontrar una solución que tomaría unas pocas líneas de código CSS y que no involucraría JavaScript. Por lo tanto, una de las primeras cosas que hice fue tratar de lograr esto. Los navegadores que utilicé para las pruebas incluyeron Chrome, Firefox y Safari en macOS y Windows 10, y Edge y Safari en iOS. Las versiones de estos navegadores eran las más recientes al momento de escribir este artículo (2018).

Soluciones solo HTML y CSS

Posicionamiento absoluto y relativo

Una de las primeras cosas que probé fue usar el posicionamiento absoluto y relativo para colocar el pie de página porque estaba acostumbrado a crear pies de página como este. La idea sería configurar mi página web al 100% de altura para que el pie de página esté siempre en la parte inferior de la página con una altura fija, mientras que el contenido ocupa el 100% menos la altura del pie de página y puedes desplazarte por eso. Como alternativa, puede configurar un padding-bottom en lugar de usar calc y configurar la altura body-container al 100 % para que el contenido de la aplicación no se superponga con el pie de página. El código CSS se veía así:

 html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }

Esta solución funciona casi de la misma manera que la solución original (que era simplemente position: fixed; ). Una ventaja de esta solución en comparación con esa es que el desplazamiento no es para toda la página, sino solo para el contenido de la página sin el pie de página. El mayor problema de este método es que en Mobile Safari, tanto el pie de página como el contenido de la aplicación se mueven al mismo tiempo. Esto hace que este enfoque sea muy problemático cuando se desplaza rápidamente:

Posicionamiento absoluto y relativo
Posicionamiento absoluto y relativo.

Otro efecto que no quería fue difícil de notar al principio, y solo me di cuenta de que estaba sucediendo después de probar más soluciones. Esto fue que fue un poco más lento desplazarse por el contenido de mi aplicación. Debido a que estamos configurando la altura de nuestro contenedor de desplazamiento al 100 % de sí mismo, esto dificulta el desplazamiento basado en movimiento/impulso en iOS. Si esa altura del 100 % es más corta (por ejemplo, cuando una altura del 100 % de 2000 px se convierte en una altura del 100 % de 900 px), el desplazamiento basado en el impulso empeora. El desplazamiento basado en movimiento rápido/impulso ocurre cuando pasas los dedos por la superficie de una pantalla táctil y la página se desplaza sola. En mi caso, quería que se produjera un desplazamiento basado en el impulso para que los usuarios pudieran desplazarse rápidamente, por lo que me mantuve alejado de las soluciones que establecían una altura del 100 %.

Otros intentos

Una de las soluciones sugeridas en la web, y que traté de usar en mi código, se muestra a continuación como ejemplo.

 html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }

Este código funciona en Chrome y Firefox en macOS de la misma manera que la solución anterior. Una ventaja de este método es que el desplazamiento no está restringido al 100 % de la altura, por lo que el desplazamiento basado en el impulso funciona correctamente. En Safari, sin embargo, el pie de página desaparece:

Pie de página faltante en macOS Safari
Falta el pie de página en macOS Safari. (Vista previa grande)

En iOS Safari, el pie de página se vuelve más corto y hay un espacio extra transparente (o blanco) en la parte inferior. Además, la capacidad de desplazarse por la página se pierde después de desplazarse hasta el final. Puede ver el espacio en blanco debajo del pie de página aquí:

Pie de página más corto en iOS Safari
Pie de página más corto en iOS Safari.

Una línea de código interesante que puede ver mucho es: -webkit-overflow-scrolling: touch; . La idea detrás de esto es que permite el desplazamiento basado en el impulso para un elemento dado. Esta propiedad se describe como "no estándar" y como "no en una pista estándar" en la documentación de MDN. Aparece como un "Valor de propiedad no válido" bajo inspección en Firefox y Chrome, y no aparece como una propiedad en Desktop Safari. No usé esta propiedad CSS al final.

Para mostrar otro ejemplo de una solución que puede encontrar y un resultado diferente que encontré, también probé el siguiente código:

 html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }

En realidad, esto funciona bien en los diferentes navegadores de escritorio, el desplazamiento basado en el impulso aún funciona y el pie de página se fija en la parte inferior y no se mueve en los navegadores web de escritorio. Quizás la parte más problemática de esta solución (y lo que la hace única) es que, en iOS Safari, el pie de página siempre tiembla y se distorsiona ligeramente y puedes ver el contenido debajo cada vez que te desplazas.

Soluciones con JavaScript

Después de probar algunas soluciones iniciales usando solo HTML y CSS, probé algunas soluciones de JavaScript. Me gustaría agregar que esto es algo que no te recomiendo que hagas y que sería mejor evitarlo. Desde mi experiencia, generalmente hay soluciones más elegantes y concisas que usan solo HTML y CSS. Sin embargo, ya había pasado mucho tiempo probando las otras soluciones, pensé que no estaría de más ver rápidamente si había algunas soluciones alternativas que usaran JavaScript.

Toque Eventos

Un enfoque para resolver el problema del rebote de desplazamiento es evitar los eventos touchmove o touchstart en la window o el document . La idea detrás de esto es que se evitan los eventos táctiles en la ventana general, mientras que se permiten los eventos táctiles en el contenido por el que desea desplazarse. Un ejemplo de código como este se muestra a continuación:

 // Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)

Probé muchas variaciones de este código para intentar que el pergamino funcionara correctamente. La prevención de touchmove en la window no hizo ninguna diferencia. Usar el document no hizo ninguna diferencia. También traté de usar tanto touchstart como touchmove para controlar el desplazamiento, pero estos dos métodos tampoco supusieron ninguna diferencia. Aprendí que ya no puedes llamar a event.preventDefault() de esta manera por motivos de rendimiento. Debe establecer la opción passive en false en el detector de eventos:

 // Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})

bibliotecas

Puede encontrar una biblioteca llamada "iNoBounce" que se creó para "evitar que su aplicación web iOS rebote al desplazarse". Una cosa a tener en cuenta al usar esta biblioteca en este momento para resolver el problema que he descrito en este artículo es que necesita que use -webkit-overflow-scrolling . Otra cosa a tener en cuenta es que la solución más concisa con la que terminé (que se describe más adelante) hace algo similar a iOS. Puede probar esto usted mismo mirando los ejemplos en su Repositorio de GitHub y comparándolos con la solución con la que terminé.

Comportamiento de desplazamiento excesivo

Después de probar todas estas soluciones, descubrí el overscroll-behavior la propiedad CSS. La propiedad CSS overscroll-behavior se implementó en Chrome 63 en diciembre de 2017 y en Firefox 59 en marzo de 2018. Esta propiedad, como se describe en la documentación de MDN, “le permite controlar el comportamiento de desbordamiento de desplazamiento del navegador: lo que sucede cuando el límite de un se alcanza el área de desplazamiento.” Esta fue la solución que terminé usando.

Todo lo que tenía que hacer era configurar overscroll-behavior en none en el body de mi sitio web y podía dejar la position del pie de página como fixed . A pesar de que el desplazamiento basado en el impulso se aplicaba a toda la página, en lugar del contenido sin el pie de página, esta solución fue lo suficientemente buena para mí y cumplió con todos mis requisitos en ese momento, y mi pie de página ya no rebotó inesperadamente en Chrome. Tal vez sea útil tener en cuenta que Edge tiene esta propiedad marcada como en desarrollo ahora. overscroll-behavior puede verse como una mejora si los navegadores aún no lo admiten.

Conclusión

Si no desea que sus encabezados o pies de página fijos reboten en sus páginas web, ahora puede usar la propiedad CSS overscroll-behavior .

A pesar del hecho de que esta solución funciona de manera diferente en diferentes navegadores (el rebote del contenido de la página aún ocurre en Safari y Edge, mientras que en Firefox y Chrome no), mantendrá fijo el encabezado o el pie de página cuando se desplace hasta la parte superior. o parte inferior de un sitio web. Es una solución concisa y en todos los navegadores probados, el desplazamiento basado en el impulso aún funciona, por lo que puede desplazarse por una gran cantidad de contenido de la página muy rápidamente. Si está creando un encabezado o pie de página fijo en su página web, puede comenzar a utilizar esta solución.