Jak implementovat Infinite Scroll ve webové aplikaci

Nekonečné rolování, na rozdíl od klasického stránkování s klikáním, umožňuje kontinuální načítání obsahu, jak uživatel prohlíží webovou stránku. Tato technika nabízí hladší uživatelský zážitek, především na mobilních zařízeních.

Pojďme se podívat, jak implementovat nekonečné rolování za použití HTML, CSS a JavaScriptu.

Konfigurace frontendu

Začněte s HTML strukturou, která poslouží jako základ pro zobrazení vašeho obsahu. Níže je uveden příklad:

 <body>
    <h2>Stránka s nekonečným rolováním</h2>
      <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>
    
    <noscript>
        Tato stránka vyžaduje JavaScript pro správné fungování.
    </noscript>
  </body>

Tato základní stránka obsahuje sadu zástupných obrázků a odkazuje na externí CSS a JavaScript soubory.

CSS stylování pro rolovatelný obsah

Pro zobrazení zástupných obrázků v mřížce, přidejte následující CSS pravidla do vašeho souboru `style.css`:

 * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    html { font-size: 62.5%; }
    body {
      font-family: Cambria, Times, "Times New Roman", serif;
    }
    h2 {
      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%);
    }

V tomto okamžiku by měla vaše stránka vypadat podobně jako na obrázku (viz originální článek).

Implementace jádra s JS

Nyní upravíme skript `script.js`. Pro implementaci nekonečného rolování musíme detekovat, kdy se uživatel posune téměř na konec obsahu stránky.

 "use strict";

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

Následně vytvoříme asynchronní funkci `fetchMoreContent()` pro načtení dalších dat.

 async function fetchMoreContent() {
    try {
      let response = await fetch("https://fakestoreapi.com/products?limit=3");
      if (!response.ok) {
        throw new Error("Chyba při načítání dat");
      }
      let data = await response.json();
      console.log(data);
    } catch (error) {
      console.error("Chyba při načítání nového obsahu:", error);
    } finally {
      console.log("Funkce fetch byla spuštěna");
    }
  }

Pro testování můžeme využít API od fakestoreapi.

Pro ověření, že se data načítají při rolování, sledujte konzoli prohlížeče:

Zjistíte, že data se načítají opakovaně, což může negativně ovlivnit výkon. Pro prevenci tohoto problému zavedeme proměnnou `isFetching`, která bude monitorovat stav načítání:

 let isFetching = false; 

Nyní upravíme funkci `fetchMoreContent()`, aby se načítala data až po dokončení předchozího načítání.

 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("Chyba při síťové komunikaci");
      }
      let data = await response.json();
    } catch (error) {
      console.error("Chyba při získávání obsahu:", error);
    } finally {
      console.log("Funkce načítání dokončena");
      isFetching = false;
    }
  }

Zobrazení nového obsahu

Aby se nový obsah zobrazoval, když uživatel rolujete, vytvořte funkci, která přidá nové obrázky do kontejneru.

Nejprve vyberte rodičovský prvek:

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

Poté definujte funkci pro vkládání nového obsahu:

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

Nakonec upravte funkci `fetchMoreContent()` tak, aby předávala získaná data funkci `displayNewContent()`.

 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("Chyba při síťovém požadavku");
          }
          let data = await response.json();
          displayNewContent(data);
      } catch (error) {
          console.error("Problém při stahování nového obsahu:", error);
      } finally {
          console.log("Data načtena");
          isFetching = false;
      }
  }

Nyní by mělo nekonečné rolování správně fungovat.

Pro zlepšení uživatelského zážitku můžeme zobrazit indikátor načítání. Začněme přidáním HTML pro indikátor:

<h2 class="loading-indicator">Načítání...</h2>

Následně vybereme tento element:

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

Vytvořte funkce pro zobrazení a skrytí indikátoru:

 function showLoadingIndicator() {
      loadingIndicator.style.display = "block";
      console.log("Načítání...");
    }
    function hideLoadingIndicator() {
      loadingIndicator.style.display = "none";
      console.log("Načítání dokončeno.");
    }

A integrujeme je do funkce `fetchMoreContent()`:

 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("Chyba při síťovém požadavku");
          }
          let data = await response.json();
          displayNewContent(data);
      } catch (error) {
          console.error("Chyba při načítání:", error);
      } finally {
          console.log("Stahování dokončeno");
          hideLoadingIndicator();
          isFetching = false;
      }
  }

Což vede k funkčnímu indikátoru načítání.

Zde jsou doporučení a osvědčené postupy:

  • Nenačítejte příliš mnoho položek najednou. Může to přetížit prohlížeč a negativně ovlivnit jeho výkon.
  • Místo načítání obsahu ihned po události rolování použijte funkci „debounce“ pro zpoždění načítání. To zabrání nadměrnému množství síťových požadavků.
  • Nekonečné rolování nemusí preferovat každý uživatel. Proto nabídněte volbu stránkování pro případ potřeby.
  • Informujte uživatele, pokud již není k dispozici další obsah, aby se zabránilo nekonečným pokusům o načtení.

Profesionální načítání obsahu

Nekonečné rolování je skvělý způsob, jak umožnit uživatelům plynule procházet váš obsah, především na mobilních zařízeních. S pomocí rad a tipů z tohoto článku jej můžete snadno implementovat na vaše webové stránky.

Nezapomeňte, že je důležité, aby uživatelé věděli, co se na stránce děje, proto zobrazujte indikátory průběhu a chybová hlášení.