Catalog Page Rendering at Scale: Pagination, Infinite Scroll, and the SEO Trade-offs
Pagination vs. infinite scroll for large video libraries — what each costs you in crawlability, Core Web Vitals, and session engagement, plus the hybrid pattern that works.
Every large video catalog faces the same structural fork: paginate the grid into discrete numbered pages, or stream tiles continuously under an infinite scroll. Both work. Both have costs. The wrong choice hurts discoverability or engagement — the right hybrid gets both.
The Honest Comparison
| Factor | Classic Pagination | Infinite Scroll | Hybrid (Load More + URL Pages) |
|---|---|---|---|
| Crawlability | Excellent — every page is a URL | Poor — crawlers see page 1 only | Excellent — scroll and URL-backed pages |
| Session depth | Lower — click friction | Highest — zero friction | High |
| Back button behavior | Perfect | Broken without state mgmt | Restorable via History API |
| Footer accessibility | Reachable | Never reachable | Reachable |
| LCP/CLS risk | Low | Moderate (layout shift on append) | Low if items have fixed aspect ratio |
Why Pure Infinite Scroll Fails Search Engines
Crawlers don’t scroll. A catalog rendered purely through scroll-triggered fetches presents exactly one page of content to indexers — every tile beyond the fold is invisible to search. For a content site where catalog pages are the primary entry point from organic search, this is fatal.
The Hybrid Pattern That Ships
- Server-render the first two rows of tiles directly into the HTML — this is what crawlers and low-end devices see, and it makes LCP fast.
- URL-synced “Load More” — appending tiles also updates
?page=Nviahistory.replaceState, so refreshes and shared links restore position. - Canonical paginated routes exist independently (
/page/2,/page/3) — thin server-rendered shells linking back into the catalog. These satisfy crawlers without degrading the scroll UX.
// IntersectionObserver-driven append with URL sync
const sentinel = document.querySelector('#load-sentinel');
let page = 1;
new IntersectionObserver(async ([entry]) => {
if (!entry.isIntersecting) return;
page++;
const html = await fetchTiles(page);
grid.insertAdjacentHTML('beforeend', html);
history.replaceState(null, '', `?page=${page}`);
}).observe(sentinel);
“The correct answer isn’t scroll or pagination — it’s scroll for humans and paginated URLs for machines, kept in sync by the History API.”
Aspect-ratio-locked tiles (aspect-ratio: 16/9) are what prevent CLS during appends — reserve the box before the image arrives. The full implementation, including crawler-safe fallback rendering, is in our catalog pagination architecture analysis.