Rolagem Infinita: Guia Completo com HTML, CSS e JavaScript

A funcionalidade de rolagem infinita proporciona um carregamento contínuo de conteúdo à medida que o utilizador desliza pela página, diferindo do método tradicional de paginação, que exige cliques para carregar. Este recurso pode aprimorar significativamente a experiência do utilizador, especialmente em dispositivos móveis, oferecendo uma navegação mais fluida.

Neste guia, exploraremos como implementar a rolagem infinita utilizando HTML, CSS e JavaScript de forma simples e eficaz.

Configuração do Front-end

Para começar, é necessário estruturar o HTML básico para exibir o conteúdo. O exemplo abaixo ilustra essa estrutura inicial:

 
<link rel="stylesheet" href="https://wilku.top/how-to-implement-infinite-scroll-in-a-web-application/style.css" />
<h1>Página de Rolagem Infinita</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>

Nesta estrutura, apresentamos uma série de imagens temporárias e referenciamos dois arquivos externos: um arquivo CSS para estilização e um arquivo JavaScript para lógica.

Estilização CSS para Conteúdo Rolável

Para organizar as imagens temporárias em formato de grade, aplique o seguinte CSS no 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%);
}

Com estas regras CSS, a sua página deverá apresentar um layout similar ao seguinte:

Implementação Essencial com JavaScript

O próximo passo é editar o arquivo `script.js`. Para implementar a rolagem infinita, é fundamental identificar quando o utilizador se aproxima do final 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();
}
});

A função `fetchMoreContent` tem como objetivo carregar mais dados temporários.

async function fetchMoreContent() {
try {
let response = await fetch("https://fakestoreapi.com/products?limit=3");
if (!response.ok) {
throw new Error("A resposta da rede não foi bem-sucedida.");
}
let data = await response.json();
console.log(data);
} catch (error) {
console.error("Houve um problema ao buscar o novo conteúdo:", error);
} finally {
console.log("A função de busca foi disparada");
}
}

Para este projeto, utilizamos a API fakestoreapi.

Para verificar se os dados estão sendo buscados corretamente ao rolar, consulte o console do navegador:

Observará que os dados são buscados repetidamente ao rolar, o que pode impactar o desempenho do dispositivo. Para otimizar, vamos criar um estado inicial para controlar a busca de dados:

let isFetching = false;

Agora, modificaremos a função `fetchMoreContent` para que ela só busque dados após a conclusão da 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("A resposta da rede não foi bem-sucedida.");
}
let data = await response.json();
} catch (error) {
console.error("Houve um problema ao buscar o novo conteúdo:", error);
} finally {
console.log("A função de busca foi disparada");
isFetching = false;
}
}

Apresentando o Novo Conteúdo

Para exibir novos elementos quando o utilizador rola a página, criaremos uma função para anexar as imagens ao contêiner principal.

Inicialmente, vamos selecionar o elemento principal:

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

Em seguida, definimos uma função para adicionar o conteúdo:

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

Finalmente, modificamos a função `fetchMoreContent` para passar 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("A resposta da rede não foi bem-sucedida.");
}
let data = await response.json();
displayNewContent(data);
} catch (error) {
console.error("Houve um problema ao buscar o novo conteúdo:", error);
} finally {
console.log("A função de busca foi disparada");
isFetching = false;
}
}

Com essas alterações, a rolagem infinita está funcional.

Para melhorar a experiência do utilizador, vamos apresentar um indicador de carregamento enquanto o novo conteúdo é buscado. Inicialmente, adicione este HTML:

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

Em seguida, selecionamos o elemento de carregamento:

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

E criamos duas funções para controlar a visibilidade do indicador de carregamento:

function showLoadingIndicator() {
loadingIndicator.style.display = "block";
console.log("Carregando...");
}
function hideLoadingIndicator() {
loadingIndicator.style.display = "none";
console.log("Carregamento concluído.");
}

Agora, adicionamos essas funções à 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("A resposta da rede não foi bem-sucedida.");
}
let data = await response.json();
displayNewContent(data);
} catch (error) {
console.error("Houve um problema ao buscar o novo conteúdo:", error);
} finally {
console.log("A função de busca foi disparada");
hideLoadingIndicator();
isFetching = false;
}
}

O resultado destas modificações proporciona uma melhor experiência ao utilizador.

Algumas práticas recomendadas a considerar incluem:

  • Evitar buscar muitos itens simultaneamente, pois isso pode sobrecarregar o navegador e prejudicar o desempenho.
  • Utilizar uma função de “debounce” para atrasar ligeiramente a busca de conteúdo após detetar um evento de rolagem. Esta prática pode evitar o excesso de solicitações à rede.
  • Oferecer uma alternativa para a paginação tradicional, dado que nem todos os utilizadores preferem a rolagem infinita.
  • Informar o utilizador quando não houver mais conteúdo a ser carregado, em vez de tentar buscar continuamente.

Aperfeiçoando o Carregamento Contínuo de Conteúdo

A rolagem infinita aprimora a navegação contínua, especialmente em dispositivos móveis. Ao aplicar as técnicas e dicas apresentadas, você poderá incorporar este recurso nos seus sites.

É fundamental prestar atenção à experiência do utilizador, incluindo a apresentação de indicadores de progresso e mensagens de erro, para assegurar uma navegação intuitiva e eficaz.