Como implementar rolagem infinita em um aplicativo da Web

A rolagem infinita permite que o conteúdo carregue continuamente à medida que os usuários descem na página, ao contrário do método clique para carregar da paginação tradicional. Esse recurso pode oferecer uma experiência mais tranquila, especialmente em dispositivos móveis.

Descubra como configurar a rolagem infinita usando HTML, CSS e JavaScript simples.

Configurando o front-end

Comece com uma estrutura HTML básica para exibir seu conteúdo. Aqui está um exemplo:

 <!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://wilku.top/how-to-implement-infinite-scroll-in-a-web-application/style.css" />
</head>
<body>
    <h1>Infinite Scroll Page</h1>

    <div class="products__list">
      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
            />
    </div>

    <script src="https://wilku.top/how-to-implement-infinite-scroll-in-a-web-application/script.js"></script>
</body>
</html>

Esta página contém uma série de imagens de espaço reservado e faz referência a dois recursos: um arquivo CSS e um arquivo JavaScript.

Estilo CSS para conteúdo rolável

Para exibir as imagens de espaço reservado em uma grade, adicione o seguinte CSS ao seu arquivo style.css:

 * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html { font-size: 62.5%; }

body {
  font-family: Cambria, Times, "Times New Roman", serif;
}

h1 {
  text-align: center;
  font-size: 5rem;
  padding: 2rem;
}

img {
  width: 100%;
  display: block;
}

.products__list {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  justify-content: center;
}

.products__list > * {
  width: calc(33% - 2rem);
}

.loading-indicator {
  display: none;
  position: absolute;
  bottom: 30px;
  left: 50%;
  background: #333;
  padding: 1rem 2rem;
  color: #fff;
  border-radius: 10px;
  transform: translateX(-50%);
}

No momento, sua página deve estar assim:

  Ocultar / Reexibir ícones da área de trabalho no OS X com comando de terminal

Implementação principal com JS

Edite script.js. Para implementar a rolagem infinita, você precisa detectar quando o usuário rolou próximo à parte inferior do contêiner de conteúdo ou da página.

 "use strict";

window.addEventListener("scroll", () => {
  if (
    window.scrollY + window.innerHeight >=
      document.documentElement.scrollHeight - 100
  ) {
    
    fetchMoreContent();
  }
});

Em seguida, crie uma função para buscar mais dados de espaço reservado.

 async function fetchMoreContent() {
  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
  }
}

Para este projeto, você pode usar a API de fakestoreapi.

Para confirmar se seus dados estão sendo buscados na rolagem, dê uma olhada no console:

Você notará que seus dados estão sendo buscados várias vezes na rolagem, o que pode ser um fator que prejudica o desempenho do dispositivo. Para evitar isso, crie um estado inicial de busca dos dados:

 let isFetching = false; 

Em seguida, modifique sua função de busca para buscar dados somente após a conclusão de uma busca anterior.

 async function fetchMoreContent() {
  if (isFetching) return;

  isFetching = true;

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    isFetching = false;
  }
}

Exibindo o novo conteúdo

Para exibir novo conteúdo quando o usuário rola a página para baixo, crie uma função que anexe as imagens ao contêiner pai.

  O que é o “efeito de porta de tela” em VR?

Primeiro, selecione o elemento pai:

 const productsList = document.querySelector(".products__list"); 

Em seguida, crie uma função para anexar conteúdo.

 function displayNewContent(data) {
  data.forEach((item) => {
    const imgElement = document.createElement("img");
    imgElement.src = item.image;
    imgElement.alt = item.title;
    productsList.appendChild(imgElement);
  });
}

Por fim, modifique sua função de busca e passe os dados buscados para a função de acréscimo.

 async function fetchMoreContent() {
  if (isFetching) return;

  isFetching = true;

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    displayNewContent(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    isFetching = false;
  }
}

E com isso, sua rolagem infinita agora funciona.

Para aprimorar a experiência do usuário, você pode exibir um indicador de carregamento ao buscar novo conteúdo. Comece adicionando este HTML.

 <h1 class="loading-indicator">Loading...</h1> 

Em seguida, selecione o elemento de carregamento.

 const loadingIndicator = document.querySelector(".loading-indicator"); 

Por fim, crie duas funções para alternar a visibilidade do indicador de carregamento.

 function showLoadingIndicator() {
  loadingIndicator.style.display = "block";
  console.log("Loading...");
}

function hideLoadingIndicator() {
  loadingIndicator.style.display = "none";
  console.log("Finished loading.");
}

Em seguida, adicione-os à função de busca.

 async function fetchMoreContent() {
  if (isFetching) return;

  isFetching = true;
  showLoadingIndicator();

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    displayNewContent(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    hideLoadingIndicator();
    isFetching = false;
 }
}

Que dá:

  Como dominar notificações no seu iPhone

Algumas práticas recomendadas a seguir incluem:

  • Não busque muitos itens simultaneamente. Isso pode sobrecarregar o navegador e prejudicar o desempenho.
  • Em vez de buscar o conteúdo imediatamente após detectar um evento de rolagem, use uma função debounce para atrasar um pouco a busca. Isso pode evitar solicitações excessivas de rede.
  • Nem todos os usuários preferem a rolagem infinita. Ofereça uma opção para usar um componente de paginação, se desejar.
  • Se não houver mais conteúdo para carregar, informe o usuário em vez de tentar buscar continuamente mais conteúdo.

Dominando o carregamento contínuo de conteúdo

A rolagem infinita permite que os usuários naveguem pelo conteúdo sem problemas e é ótima para pessoas que usam dispositivos móveis. Se você usar as dicas e conselhos importantes deste artigo, poderá adicionar esse recurso aos seus sites.

Lembre-se de pensar em como os usuários se sentem ao usar seu site. Mostre coisas como sinais de progresso e notas de erro para garantir que o usuário saiba o que está acontecendo.