Controla tu desplazamiento: personaliza los efectos de "deslizar hacia abajo para actualizar" y "desbordamiento",

A modo de resumen

La propiedad CSS overscroll-behavior permite que los desarrolladores anulen la el comportamiento de desbordamiento predeterminado de tu navegador al llegar a la parte superior/inferior de contenido. Los casos de uso incluyen inhabilitar la función "deslizar hacia abajo para actualizar" en dispositivos móviles, lo que quita el brillo en el desplazamiento y los efectos de bandas elásticas, y evita que el contenido de la página se desplace cuando está debajo de una ventana modal o de una superposición.

Información general

Límites de desplazamiento y encadenamiento de desplazamientos

Encadenamiento de desplazamientos en Chrome para Android

El desplazamiento es una de las formas más fundamentales de interactuar con una página, pero puede ser difícil lidiar con ciertos patrones de UX debido a la peculiar los comportamientos predeterminados. Por ejemplo, tomemos un panel de apps con una gran cantidad de elementos por los que el usuario debe desplazarse. Cuando llegan al fondo, el contenedor de desbordamiento detiene el desplazamiento porque no hay más contenido para consumir. En otras palabras, el usuario alcanza un "límite de desplazamiento". Pero observa lo que sucede si el usuario sigue desplazar. El contenido detrás del panel lateral comienza a desplazarse. El desplazamiento es tomada por el contenedor superior; la página principal en el ejemplo.

Resulta que este comportamiento se denomina encadenamiento de desplazamiento. la configuración predeterminada comportamiento cuando te desplazas por el contenido. La configuración predeterminada suele ser agradable, a veces no es deseable ni inesperado. Es posible que algunas apps quieran proporcionar una experiencia del usuario diferente cuando alcanza un límite de desplazamiento.

Efecto tirar para actualizar

"Arrastrar para actualizar" es un gesto intuitivo popularizado por aplicaciones para dispositivos móviles como Facebook y Twitter. Si acercas la atención a un feed social y la lanzas, se crean espacio para que se carguen las publicaciones más recientes. De hecho, esta UX en particular tiene se han vuelto tan populares que los navegadores para dispositivos móviles, como Chrome en Android, han adoptado el mismo efecto. Si deslizas el dedo hacia abajo en la parte superior de la página, se actualiza toda la página:

. el gesto de deslizar para actualizar personalizado de Twitter
cuando se actualiza un feed en su AWP.
. La acción nativa de deslizar para actualizar de Chrome para Android
actualiza todo .

En situaciones como la PWA de Twitter, se recomienda inhabilitar la acción nativa "deslizar hacia abajo para actualizar". ¿Por qué? En este es probable que no quieras que el usuario actualice la página accidentalmente. Hay también la posibilidad de ver una animación de actualización doble. De manera alternativa, podría ser más amable para personalizar la acción del navegador y alinearlo más estrechamente con la actividad desarrollo de la marca. Lamentablemente, este tipo de personalización difíciles de llevar a cabo. Los desarrolladores terminan escribiendo código JavaScript innecesario, agregar no pasivo objetos de escucha táctiles (que bloquean el desplazamiento) o adherir toda la página en un 100 vw/vh <div> (para evitar que la página se desborde) Estas soluciones alternativas tienen negativa bien documentada en el rendimiento del desplazamiento.

¡Podemos hacerlo mejor!

Presentamos overscroll-behavior

La propiedad overscroll-behavior es una nueva función de CSS que controla el comportamiento de lo que sucede cuando te desplazas sobre un contenedor (incluida la esta página). Puedes usarlo para cancelar el encadenamiento de desplazamiento, inhabilitar o personalizar acción de deslizar para actualizar, inhabilitar los efectos de banda elástica en iOS (cuando Safari implementa overscroll-behavior) y mucho más. La mejor parte es que usar overscroll-behavior no afecta negativamente a el rendimiento de la página, como los trucos mencionados en la introducción.

La propiedad tiene tres valores posibles:

  1. auto: Predeterminado. Los desplazamientos que se originan en el elemento pueden propagarse a elementos principales.
  2. contain: Evita el encadenamiento de desplazamiento. Los desplazamientos no se propagan a los principales pero se muestran los efectos locales dentro de él. Por ejemplo, el brillo del sobredesplazamiento en Android o el efecto banda elástica en iOS que notifica al usuario cuando alcanzan un límite de desplazamiento. Nota: Con overscroll-behavior: contain en el elemento html evita el sobredesplazamiento. acciones de navegación.
  3. none: Es igual que contain, pero también evita los efectos de desplazamiento dentro del elemento. el nodo en sí (p.ej., brillo del sobredesplazamiento de Android o banda elástica de iOS).

Analicemos algunos ejemplos para ver cómo usar overscroll-behavior.

Evita que los desplazamientos escapen de un elemento de posición fija

Situación del cuadro de chat

El contenido que aparece debajo de la ventana de chat también se desplaza :(

Considera un cuadro de chat de posición fija que se ubica en la parte inferior de la página. El la intención es que el cuadro de chat sea un componente independiente y que se desplace independiente del contenido detrás de ella. Sin embargo, debido al encadenamiento de desplazamiento, el El documento comienza a desplazarse en cuanto el usuario presiona el último mensaje del chat. de Google Chat.

Para esta app, es más apropiado tener desplazamientos que se originen en la cuadro de chat permanecen dentro del chat. Podemos hacerlo realidad agregando overscroll-behavior: contain al elemento que contiene los mensajes de chat:

#chat .msgs {
  overflow: auto;
  overscroll-behavior: contain;
  height: 300px;
}

Básicamente, creamos una separación lógica entre el desplazamiento del cuadro de chat el contexto y la página principal. El resultado final es que la página principal permanece en su lugar cuando el usuario llega a la parte superior o inferior del historial de chat. Los desplazamientos que comienzan en la la ventana de chat no se propagan.

Caso de superposición de página

Otra variación del "desplazamiento inferior" es cuando ves contenido desplazarse detrás de una superposición de posición fija Un sorteo sin fin overscroll-behavior está en orden. El navegador intenta ser útil, pero pero hace que el sitio se vea con errores.

Ejemplo (modal con y sin overscroll-behavior: contain):

. Antes: El contenido de la página se desplaza debajo de la superposición.
. Después: El contenido de la página no se desplaza debajo de la superposición.

Cómo inhabilitar la función "deslizar para actualizar"

Solo se puede desactivar la acción de deslizar para actualizar con una sola línea de CSS. Solo prevenir el encadenamiento de desplazamiento en todo el elemento que define el viewport. En la mayoría de los casos, es <html> o <body>:

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

Con esta simple adición, corregiremos las animaciones de doble tirar para actualizar en la demostración del cuadro de chat En su lugar, implementa un efecto personalizado con una animación de carga más prolija. El toda la carpeta Recibidos también se desenfoca a medida que esta se actualiza:

Antes
Después

Este es un fragmento del código completo:

<style>
  body.refreshing #inbox {
    filter: blur(1px);
    touch-action: none; /* prevent scrolling */
  }
  body.refreshing .refresher {
    transform: translate3d(0,150%,0) scale(1);
    z-index: 1;
  }
  .refresher {
    --refresh-width: 55px;
    pointer-events: none;
    width: var(--refresh-width);
    height: var(--refresh-width);
    border-radius: 50%;
    position: absolute;
    transition: all 300ms cubic-bezier(0,0,0.2,1);
    will-change: transform, opacity;
    ...
  }
</style>

<div class="refresher">
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
</div>

<section id="inbox"><!-- msgs --></section>

<script>
  let _startY;
  const inbox = document.querySelector('#inbox');

  inbox.addEventListener('touchstart', e => {
    _startY = e.touches[0].pageY;
  }, {passive: true});

  inbox.addEventListener('touchmove', e => {
    const y = e.touches[0].pageY;
    // Activate custom pull-to-refresh effects when at the top of the container
    // and user is scrolling up.
    if (document.scrollingElement.scrollTop === 0 && y > _startY &&
        !document.body.classList.contains('refreshing')) {
      // refresh inbox.
    }
  }, {passive: true});
</script>

Cómo inhabilitar los efectos de resplandor y banda elástica de sobredesplazamiento

Para inhabilitar el efecto de rebote al alcanzar un límite de desplazamiento, utiliza overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
. Antes: Cuando se presiona el límite de desplazamiento, se muestra un brillo.
Después: Brillo inhabilitado.

Demostración completa

Cuando se junta todo, demobox en el chat overscroll-behavior para crear una animación personalizada de "deslizar hacia abajo para actualizar" e inhabilita los desplazamientos para que no escapen del widget del cuadro de chat. Esto proporciona una óptima experiencia del usuario que hubiera sido difícil de lograr sin CSS overscroll-behavior

. Ver demostración | Fuente