Controle sua rolagem, personalizando efeitos de puxar para atualizar e estourar

Texto longo, leia o resumo

A propriedade CSS overscroll-behavior permite que os desenvolvedores modifiquem as comportamento de rolagem flutuante padrão do navegador ao atingir o topo/fim do conteúdo. Os casos de uso incluem desativar a opção "puxar para atualizar" em dispositivos móveis, removendo brilho de rolagem e efeitos de borracha, e impedir que o conteúdo da página seja rolado quando estiver sob uma modal/sobreposição.

Contexto

Limites e encadeamento de rolagem

Encadeamento de rolagem no Chrome Android.

A rolagem é uma das maneiras mais fundamentais de interagir com uma página, mas alguns padrões de UX podem ser complicados de lidar por causa das características peculiares comportamentos padrão. Por exemplo, considere uma gaveta de apps com um grande número de itens que o usuário talvez tenha que rolar. Quando eles chegam ao mínimo, o contêiner flutuante interrompe a rolagem porque não há mais conteúdo para consumir. Em outras palavras, o usuário atinge um "limite de rolagem". Mas observe o que acontece se o usuário continuar rolar a tela. O conteúdo atrás da gaveta começa a rolar. A rolagem é assumido pelo contêiner pai. da própria página principal no exemplo.

Esse comportamento é chamado de encadeamento de rolagem. o padrão do navegador ao rolar o conteúdo. Muitas vezes, o padrão é muito bom, mas às vezes não é desejável ou até mesmo inesperado. Certos apps podem querer oferecem uma experiência do usuário diferente quando ele atinge um limite de rolagem.

O efeito "puxar para atualizar"

Puxar para atualizar é um gesto intuitivo popularizado por apps para dispositivos móveis, como Facebook e Twitter. Puxar para baixo em um feed social e liberar cria novos espaço para postagens mais recentes serem carregadas. Na verdade, essa UX específica se tornaram tão populares que navegadores para dispositivos móveis, como o Chrome no Android, adotaram o mesmo efeito. Deslizar para baixo no topo da página atualiza toda a página:

A opção personalizada "puxar para atualizar" do Twitter
ao atualizar um feed em o PWA.
A ação nativa de arrastar para atualizar do Chrome Android
atualiza todo o página.

Para situações como o PWA do Twitter, pode fazer sentido desativar a ação nativa "puxar para atualizar". Por quê? Neste app, é provável que você não queira que o usuário atualize a página sem querer. Há também é possível ver uma animação de atualização dupla. Também pode ser seria mais legal personalizar a ação do navegador, alinhando-o mais de perto ao código branding. O lado negativo é que esse tipo de personalização foi difíceis de realizar. Os desenvolvedores escrevem JavaScript desnecessário, adicionam não passivo listeners de toque (que bloqueiam a rolagem) ou fixa a página inteira em um bloco de 100 vw/vh <div> (para evitar o estouro da página). Essas soluções têm negativa bem documentada no desempenho de rolagem.

Podemos melhorar!

Conheça o overscroll-behavior

A propriedade overscroll-behavior é um novo recurso CSS que controla o comportamento do que acontece quando você rola a tela por cima do contêiner (incluindo o página em si). É possível usá-lo para cancelar o encadeamento de rolagem, desativar/personalizar a ação de arrastar para atualizar, desativar os efeitos de borracha no iOS (quando o Safari implementa overscroll-behavior) e muito mais. A melhor parte é que usar overscroll-behavior não afeta negativamente o desempenho da página, como as dicas mencionadas na introdução.

A propriedade aceita três valores possíveis:

  1. auto: padrão. Os rolamentos originados no elemento podem se propagar para elementos ancestrais.
  2. contain: evita o encadeamento de rolagem. As rolagens não se propagam para os ancestrais mas são mostrados efeitos locais dentro do nó. Por exemplo, o brilho da rolagem no Android e o efeito borracha no iOS que notifica o usuário quando atingem um limite de rolagem. Observação: o uso overscroll-behavior: contain no elemento html impede a rolagem esticada ações de navegação.
  3. none: o mesmo que contain, mas também impede efeitos de rolagem dentro o próprio nó (por exemplo, brilho de rolagem do Android ou aplicação de borracha do iOS).
.

Vamos conferir alguns exemplos para aprender a usar overscroll-behavior.

Impedir que as rolagens escapem de um elemento de posição fixa

O cenário da caixa de chat

O conteúdo abaixo da janela de chat também rola :(

Considere uma caixa de chat fixa, posicionada na parte de baixo da página. A intenção é que a caixa de chat seja um componente independente e role separadamente do conteúdo por trás dele. No entanto, devido ao encadeamento de rolagem, o documento começa a rolar assim que o usuário clica na última mensagem no chat. história.

Para este app, é mais apropriado ter rolagens originadas dentro do permanecem dentro do chat. Podemos fazer isso acontecer adicionando overscroll-behavior: contain no elemento que contém as mensagens de chat:

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

Essencialmente, estamos criando uma separação lógica entre a rolagem da caixa de chat contexto e a página principal. O resultado final é que a página principal permanece parada quando o usuário chega à parte superior/inferior do histórico de bate-papo. Rolagens que começam no não sejam propagadas para fora do Google.

Cenário de sobreposição de página

Outra variação da função "underscroll" é quando você vê o conteúdo rolagem atrás de uma sobreposição de posição fixa. Uma surpresa morta overscroll-behavior está em ordem! O navegador está tentando ser útil, mas isso acaba fazendo o site parecer com bugs.

Exemplo - modal com e sem overscroll-behavior: contain:

Antes: o conteúdo da página rola abaixo da sobreposição.
Depois: o conteúdo da página não rola abaixo da sobreposição.

Como desativar o recurso "puxar para atualizar"

A desativação da ação de arrastar para atualizar é uma única linha de CSS. Apenas evitar o encadeamento de rolagem em todo o elemento que define a janela de visualização. Na maioria dos casos, <html> ou <body>:

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

Com essa adição simples, consertamos as animações duplas de puxar para atualizar demonstração da caixa de bate-papo e pode implemente um efeito personalizado que usa uma animação de carregamento mais organizada. A A caixa de entrada inteira também é desfocada conforme a caixa de entrada é atualizada:

Antes
Depois

Aqui está um snippet 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>

Como desativar o brilho de rolagem e os efeitos de borracha

Para desativar o efeito de oscilação ao atingir um limite de rolagem, use overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
Antes: pressionar o limite de rolagem mostra um brilho.
Depois: brilho desativado.

Demonstração completa

Juntando tudo, o total usos da demonstração da caixa de chat overscroll-behavior para criar uma animação personalizada de puxar para atualizar e desativar o escape dos rolagens do widget da caixa de chat. Isso oferece um ótimo experiência do usuário que teria sido difícil de alcançar sem o CSS. overscroll-behavior:

Veja a demonstração | Fonte