Implementing Infinite Scroll
Implementing infinite scroll to load content dynamically as users scroll. Use when building web apps requiring continuous content loading wi
The Engineer's Guide to Infinite Scroll: Performance, Accessibility, and Zero Layout Shifts
We built this skill so you don't have to debug rootMargin vs threshold at 2 AM or explain to your PM why the screen reader can't find the "Load More" button.
Install this skill
npx quanta-skills install implementing-infinite-scroll
Requires a Pro subscription. See pricing.
Infinite scroll is the default pattern for feeds, chat logs, and dashboards. But the naive implementation is a performance trap. Engineers reach for window.addEventListener('scroll', ...) and immediately introduce jank, memory leaks, and battery drain on mobile devices. Even when you switch to the IntersectionObserver API, you're still responsible for managing DOM bloat, handling hydration mismatches in SSR frameworks, and ensuring the injected content is announced correctly to assistive technologies.
The IntersectionObserver API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport [1]. That's the easy part. The hard part is wiring that observation into a state management system that doesn't thrash the main thread, setting up preloading margins so the next chunk fetches before the user notices, and validating that your component props match the accessibility contract.
If you're using React, you're fighting useEffect cleanup cycles and re-renders. If you're doing vanilla JS, you're manually managing observer lifecycles. Most teams patch this together with copy-pasted snippets, resulting in inconsistent behavior across components. We created the Implementing Infinite Scroll skill to give you a single source of truth: a production-grade implementation, framework templates, accessibility references, and a validator that catches configuration errors before you hit git commit.
Pagination is Dead, But Infinite Scroll is a Minefield
Pagination is fine for documents. It's terrible for feeds. Users expect continuous content. But "continuous" doesn't mean "dump everything into the DOM."
The biggest mistake we see is treating infinite scroll as a simple fetch loop. You end up with scroll listeners firing hundreds of times per second, triggering debounced fetches that race each other. You get multiple loading spinners. You get layout shifts when images load asynchronously. You get memory leaks because you never call unobserve() on old targets.
The IntersectionObserver interface solves the event spam, but it introduces new complexity. You need to understand how the observer handles thresholds, how rootMargin affects preload timing, and how to handle the IntersectionObserverEntry object that tells you when a target actually crosses the boundary [2]. If you're watching multiple targets, you need to manage the observer's target set carefully [5].
Worse, infinite scroll breaks user orientation. Without proper landmarks, users can't jump to specific sections or return to the top easily. NN/g research highlights that infinite scroll variants should include pagination landmarks for orientation, even if the primary interaction is scrolling [8]. If you don't implement ARIA roles, screen reader users are blind to the new content. They don't know the feed updated. They don't know where they are in the list. You've built a feature that excludes a significant portion of your user base.
The Cost of a Broken Infinite Scroll Implementation
What happens when you ignore these constraints? The cost compounds quickly.
Performance degradation: Without virtualization or careful unmounting, the DOM grows linearly with scroll depth. On a low-end Android device, a feed with 500 items can hit memory limits, causing the browser to throttle or crash. P95 latency for scroll events spikes as the browser struggles to paint the oversized DOM. You lose trust. Users abandon the app. Accessibility failures: If you inject content withoutaria-live regions or proper focus management, screen readers don't announce updates. Users with motor impairments can't navigate efficiently. You risk compliance issues and PR damage. Fixing this later requires refactoring the component architecture, not just adding a prop.
Integration debt: A messy infinite scroll component becomes a bottleneck for other features. If you need to add sorting or filtering later, the scroll offset calculations break. If you try to combine infinite scroll with implementing lazy loading for images, you get conflicting intersection observers fighting over the same viewport. If you're building a dashboard, integrating this with an implementing data table with sort filter component requires careful state synchronization to prevent the table from jumping when the feed loads.
SEO penalties: Search engines struggle with infinite scroll. If you don't implement server-side rendering with cursor-based pagination, your content isn't indexed. You lose organic traffic. Fixing this requires restructuring your API to support cursor pagination, which ties back to your REST API Design Pack strategy.
How a Team Reclaimed P95 Latency and Accessibility Scores
Imagine a team building a social feed for a gig-economy platform. They had 200k DAU. The feed was built with a scroll listener and a simple offset parameter. P95 latency was 420ms. Mobile battery drain was 15% per hour. Accessibility score was 45. Screen reader users reported the feed was "inaccessible."
They rebuilt using the patterns in this skill. Here's what changed:
IntersectionObserver: They replaced the scroll listener with an observer watching a sentinel element at the bottom of the feed. The observer fires only when the sentinel enters the viewport [6]. This eliminated event spam and reduced main thread blocking by 90%.rootMargin for preloading: They set rootMargin: '200px' so the observer triggered the fetch 200px before the user reached the bottom. This made the next chunk appear instantly, masking network latency.role="feed" to the container and aria-live="polite" to the content region. Screen readers now announce new items. They also added aria-label to the sentinel for orientation.dataLength, next, and hasMore props. This caught three misconfigured components that were causing infinite loops.useInfiniteQuery.The results were dramatic. P95 latency dropped to 110ms. Mobile battery drain fell to 4% per hour. Accessibility score jumped to 98. User retention on the feed page increased by 12% because the experience felt seamless.
The key was using IntersectionObserverEntry properties correctly. They checked isIntersecting to trigger loads and boundingClientRect to debug edge cases [7]. They also used threshold: [0, 0.25] to catch partial intersections, ensuring the fetch triggered even if the user scrolled slowly.
What Changes Once You Install the Infinite Scroll Skill
With this skill installed, you get a production-ready implementation that handles the edge cases most teams miss.
Framework-agnostic performance: The vanilla JS template usesIntersectionObserver with v2 visibility tracking, rootMargin preloading, and debounced load triggers. It's optimized for maximum performance on any framework. If you're using React, the template integrates with react-infinite-scroll-component and supports SWR/TanStack Query patterns for data fetching.
Accessibility out of the box: The ARIA feed pattern reference gives you canonical knowledge on live region semantics, keyboard navigation, and focus management. You don't have to guess how to announce new content. The templates include aria-live and role="feed" by default.
Validation before you ship: The validator script parses your TSX/JSX files and checks for required props. If you forget hasMore or misconfigure dataLength, the script exits non-zero. This catches errors in CI/CD before they reach production. The JSON schema defines the exact prop contract, so you can programmatically validate implementations.
Seamless integration: If you're building a complex app, you can combine this skill with building settings preferences page to let users toggle infinite scroll vs. pagination based on their preference. You can also integrate with implementing lazy loading for images to further optimize performance. The Next.js example demonstrates proper hydration handling, so you don't get mismatched content between server and client.
Error handling and resilience: The templates include error boundaries and retry logic. If a fetch fails, the user sees a clear message and can retry. The state management handles optimistic updates and stale-while-revalidate patterns, so the UI stays responsive even when the network is flaky.
What's in the Implementing Infinite Scroll Pack
skill.md— Orchestrator guide that defines the infinite scroll pattern, accessibility requirements, performance constraints, and references all other files in the package for implementation, validation, and examples.templates/react-infinite-scroll.tsx— Production-grade React component wrapper using react-infinite-scroll-component with TypeScript types, SWR/TanStack Query integration patterns, pull-to-refresh support, and proper state management.templates/vanilla-intersection-observer.js— Framework-agnostic vanilla JS implementation using the IntersectionObserver API with v2 visibility tracking, rootMargin preloading, and debounced load triggers for maximum performance.references/aria-feed-pattern.md— Canonical knowledge on the ARIA feed role, live region semantics, keyboard navigation, focus management, and screen reader announcements for dynamic content injection.references/performance-optimization.md— Canonical knowledge on content-visibility, CSS scroll-snap, virtualization strategies, lazy image loading, and preventing layout shifts during infinite scroll rendering.examples/nextjs-feed-client.tsx— Worked example for Next.js App Router demonstrating a Client Component with cursor-based pagination, error boundaries, and proper hydration handling.examples/tanstack-query-integration.tsx— Worked example integrating react-infinite-scroll-component with @tanstack/react-query useInfiniteQuery, handling page params, optimistic updates, and stale-while-revalidate.validators/prop-schema.json— JSON Schema defining the required and optional props for the InfiniteScroll component, used to programmatically validate component implementations against the package standards.scripts/validate-component.sh— Executable bash script that parses a target TSX/JSX file, extracts component props/state, validates against prop-schema.json, and exits non-zero if required props (dataLength, next, hasMore) are missing or misconfigured.tests/test-validator.sh— Test harness that runs validate-component.sh against a mock component file, asserts expected pass/fail exit codes, and validates schema compliance programmatically.
Install and Ship
Stop writing scroll listeners that leak memory and break accessibility. Start shipping infinite scroll that works on every device and for every user.
Upgrade to Pro to install the Implementing Infinite Scroll skill. You get the templates, the validator, the accessibility references, and the examples. You get a production-grade implementation that you can trust. Install it, run the validator, and ship with confidence.
References
- Intersection Observer API - MDN Web Docs — developer.mozilla.org
- IntersectionObserver - Web APIs | MDN — developer.mozilla.org
- IntersectionObserverEntry - Web APIs - MDN Web Docs — developer.mozilla.org
- IntersectionObserver: observe() method - Web APIs | MDN — developer.mozilla.org
- IntersectionObserverEntry: isIntersecting property - Web APIs — developer.mozilla.org
- Infinite Scrolling: When to Use It, When to Avoid It — nngroup.com
Frequently Asked Questions
How do I install Implementing Infinite Scroll?
Run `npx quanta-skills install implementing-infinite-scroll` in your terminal. The skill will be installed to ~/.claude/skills/implementing-infinite-scroll/ and automatically available in Claude Code, Cursor, Copilot, and other AI coding agents.
Is Implementing Infinite Scroll free?
Implementing Infinite Scroll is a Pro skill — $29/mo Pro plan. You need a Pro subscription to access this skill. Browse 37,000+ free skills at quantaintelligence.ai/skills.
What AI coding agents work with Implementing Infinite Scroll?
Implementing Infinite Scroll works with Claude Code, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Warp, and any AI coding agent that reads skill files. Once installed, the agent automatically gains the expertise defined in the skill.