Viciado em Internet Profissional • Entusiasta de Jogos • Criador de Tecnologia
Viciado em Internet Profissional • Entusiasta de Jogos • Criador de Tecnologia

Seis coisas que aprendi sobre a rolagem elástica do Safari no iOS

Para resolver um problema de rolagem no Safari no iOS, tive que criar a minha própria página de teste simples!
Esta página foi traduzida do inglês pelos meus estagiários de IA altamente motivados para sua conveniência. Eles ainda estão aprendendo, então alguns erros podem ter passado despercebidos. Para informações mais precisas, consulte a versão em inglês.
Lar Blog Seis coisas que aprendi sobre a rolagem elástica do Safari no iOS

Observe que este post foi publicado em junho de 2015, portanto, dependendo de quando você o ler, algumas partes podem estar desatualizadas. Infelizmente, nem sempre consigo manter estes posts totalmente atualizados para garantir que as informações permaneçam precisas.

Para resolver um problema recente de rolagem no Safari no iOS, precisei criar minha própria página de teste simples e, em seguida, aplicar todas as informações e combinações que consegui encontrar na internet para tentar resolver o problema.

Abaixo está uma breve visão geral do que descobri durante este processo.

Minha página de teste

Minha página de teste era bem básica. Ela consistia em dados simulados em uma div estática para representar a página, junto com uma div fixa para representar um menu sobreposto acima da página, assim.

Uma captura de tela de um menu lateral em HTML aberto no iOS Safari

O código-fonte completo da página pode ser encontrado no final deste post do blog.

Entendendo o comportamento padrão

A primeira coisa que fiz foi tentar entender o comportamento padrão do Safari no iOS. A observação mais marcante foi que, quando você rolava até o final do menu, o corpo da página exibia um 'efeito elástico' — um recurso embutido no Safari.

uma captura de tela animada do efeito elástico problemático no iOS Safari na parte inferior da página

A mesma coisa aconteceu ao rolar até o topo do menu.

uma captura de tela animada do efeito elástico problemático no iOS Safari no topo da página

No entanto, o primeiro problema que percebi foi que, se você rolar continuamente até o topo ou o fim da página, o Safari começa a apresentar falhas de renderização tanto no fundo da página quanto no menu.

Não tenho certeza do motivo, mas suspeito que tenha a ver com o recurso de seleção elástica.

uma captura de tela animada do problema com falhas no Safari do iOS, na parte inferior da página

Entendendo o que a regra CSS "-webkit-overflow-scrolling" faz

A próxima coisa que fiz foi aplicar a regra CSS -webkit-overflow-scrolling ao menu, o que ativa a rolagem baseada em momentum.

Como mostrado na imagem abaixo, a rolagem continua mesmo após eu deslizar o dedo.

exibindo o problema de rolagem com inércia no iOS Safari

Mas ele também adiciona um efeito elástico ao rolar até o topo ou o rodapé, como mostrado abaixo.

exibindo o problema de rolagem com inércia no iOS Safari, com o efeito de borracha

O usuário precisa esperar até o fim do efeito elástico

Durante meus testes, também percebi que, enquanto o efeito elástico está em andamento, o usuário não consegue mudar o foco para outro elemento até que a animação tenha sido concluída.

No exemplo abaixo, primeiro rolo a página de fundo e, em seguida, tento rapidamente rolar o menu, mas acabo continuando a rolar a página de fundo.

mostrando que a página em segundo plano está rolando no iOS Safari

No entanto, se eu esperar um instante até o efeito terminar, posso então começar a rolar o menu.

exibindo a espera até o término do efeito elástico no Safari do iOS

Como impedir que a página em segundo plano role

Durante meus testes, também percebi que, enquanto o efeito elástico está em andamento, o usuário não consegue mover o foco para outro elemento até que a animação termine completamente.

Com base nesta resposta do Stack Overflow, você pode garantir que elementos com disable-scrolling não executem a ação de rolagem padrão quando o evento touchmove for acionado.

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(); } };

E então aplique a classe disable-scrolling na div da página:

<div class="page disable-scrolling">

Isso funciona mais ou menos, mas testes mais aprofundados mostram que a página de fundo ainda pode, às vezes, rolar quando você atinge o topo ou o fim do menu.

mostrando que o fundo ainda está sendo rolado

Como evitar a rolagem excessiva da página de fundo

Ao aplicar esta solução, torna-se possível evitar o "overscrolling". Isso significa que, quando um elemento é rolado até o topo ou o fundo, a rolagem não continua para o corpo da página.

Como resultado, o corpo da página fica impedido de rolar, o que também impede o surgimento do efeito elástico.

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

O que este trecho de JavaScript faz é impedir que o elemento alcance o topo nem o fundo, mantendo-o a apenas 1 pixel de distância.

Se a posição de rolagem nunca atingir o topo nem o fundo, o overscroll nunca poderá ocorrer.

demonstração de como evitar a rolagem excessiva, sem nunca chegar ao topo nem ao fim

Como evitar a rolagem excessiva para a página de segundo plano

Se você quiser remover o efeito elástico da rolagem do menu — seja por motivos estéticos ou porque, como no meu caso, ele causou falhas adicionais de renderização — basta remover a regra CSS -webkit-overflow-scrolling.

No entanto, como pode ver abaixo, você também perde o impulso da rolagem suave.

demonstração completa para prevenir o rubberbanding no iOS Safari

Código-fonte de toda a página

Aqui está o código-fonte completo da 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 pela primeira vez em 10/06/2015. Última atualização em 10/06/2015.

📺 Assista ao vídeo mais recente do Squeaky!

Como adicionar legendas simples em tempo real à sua transmissão ao vivo