Accessible Infinite Scroll and Pagination: Content Loading That Respects Users
Accessible Infinite Scroll and Pagination: Content Loading That Respects Users
How content loads as users browse — pagination, infinite scroll, or “load more” buttons — directly affects accessibility. Infinite scroll, the darling of social media feeds, is one of the most problematic patterns for keyboard users, screen reader users, and users with cognitive disabilities. Understanding each pattern’s trade-offs helps you choose the approach that serves all users.
The Problem With Infinite Scroll
Infinite scroll continuously loads new content as the user scrolls toward the bottom of the page. Accessibility issues:
Keyboard trap: Keyboard users Tab through content sequentially. With infinite scroll, new content loads before they can reach the footer, navigation, or any element below the feed. The footer becomes unreachable.
Screen reader disorientation: When new content injects above or around the user’s current position, screen readers may jump to unexpected locations or re-announce content.
Cognitive overload: An endless stream with no defined beginning or end makes it difficult to understand how much content exists, where the user is within it, or when to stop browsing.
No URL for position: Users cannot bookmark or share their current position in an infinite scroll. If they navigate away and return, they start from the beginning.
Performance degradation: As hundreds or thousands of items load, page performance degrades, especially on low-powered devices and assistive technology that processes the full DOM.
Pattern 1: Traditional Pagination
Pagination divides content into discrete pages with navigation controls. It is the most accessible pattern for content browsing.
<nav aria-label="Search results pagination">
<ul>
<li><a href="?page=1" aria-label="Page 1">1</a></li>
<li><a href="?page=2" aria-current="page" aria-label="Page 2, current page">2</a></li>
<li><a href="?page=3" aria-label="Page 3">3</a></li>
<li><span aria-hidden="true">...</span></li>
<li><a href="?page=12" aria-label="Page 12">12</a></li>
<li><a href="?page=3" aria-label="Next page">Next</a></li>
</ul>
</nav>
Accessibility Strengths
- Footer is always reachable: Content has a defined end on each page
- URL-based state: Each page has a unique URL for bookmarking and sharing
- Clear position: “Page 2 of 12” communicates location in the content set
- Predictable content volume: Users know how much content is on each page
- Performance: Only the current page’s content is in the DOM
Implementation Requirements
aria-current="page": On the current page numberaria-labelon each pagination link: “Page 3” rather than just “3”aria-labelon the<nav>: “Search results pagination” to distinguish from other navigation- Result count: Announce the total: “Showing results 11-20 of 156”
- Page change announcement: When navigating to a new page (especially in SPAs), announce the change: “Page 2 loaded, showing results 11-20” via an
aria-liveregion
Pattern 2: Load More Button
A “Load More” button at the end of the initial content batch lets users explicitly request more content. This is a strong middle ground between pagination and infinite scroll.
<div role="feed" aria-label="Product listings">
<article aria-setsize="156" aria-posinset="1">...</article>
<article aria-setsize="156" aria-posinset="2">...</article>
<!-- ... items 1-20 ... -->
<article aria-setsize="156" aria-posinset="20">...</article>
</div>
<div class="load-more-section">
<p>Showing 20 of 156 products</p>
<button id="load-more">Load more products</button>
</div>
Focus Management After Loading
When new content loads, move focus to the first new item so keyboard users continue from where they left off:
loadMoreButton.addEventListener('click', async () => {
const newItems = await fetchNextPage();
container.append(...renderItems(newItems));
// Move focus to the first new item
newItems[0].querySelector('a, button, [tabindex]')?.focus();
// Update count
countDisplay.textContent = `Showing ${totalLoaded} of ${totalCount} products`;
});
Advantages
- The footer remains reachable (content ends at the “Load More” button)
- Users control when more content loads
- The count display communicates progress
- Focus management keeps keyboard users oriented
Pattern 3: ARIA Feed (If You Must Infinite Scroll)
If infinite scroll is a hard requirement (social media feeds, real-time activity streams), the W3C ARIA role="feed" pattern provides the best accessible implementation:
<div role="feed" aria-label="Activity feed" aria-busy="false">
<article role="article" aria-setsize="-1" aria-posinset="1" aria-labelledby="post-1-title">
<h2 id="post-1-title">Sarah shared a project update</h2>
<p>The new dashboard is ready for review...</p>
</article>
<article role="article" aria-setsize="-1" aria-posinset="2" aria-labelledby="post-2-title">
<h2 id="post-2-title">Marcus commented on your document</h2>
<p>Great work on the accessibility audit...</p>
</article>
</div>
Feed Keyboard Interaction
- Page Down: Move focus to the next article in the feed
- Page Up: Move focus to the previous article in the feed
- Ctrl+End: Move focus past the feed (to reach footer/navigation)
The Ctrl+End shortcut is critical — it provides the escape hatch that lets keyboard users bypass the infinite feed to reach page-level navigation.
Feed Attributes
aria-setsize="-1": Indicates the total set size is unknown (common with infinite feeds)aria-posinset: The 1-based position of each article, giving screen readers context: “Article 47 of unknown total”aria-busy="true": Set during loading to prevent screen readers from announcing incomplete content. Follow loading state patterns.
Complementary Patterns
Jump to Top/Bottom
Provide visible buttons to jump to the beginning and end of loaded content, giving keyboard users quick navigation within long feeds.
Filtering and Search
When content sets are large, provide filtering or search with autocomplete so users can find specific items without scrolling through hundreds of results.
Item Count
Always communicate the scope:
- Pagination: “Page 2 of 12 (156 results)”
- Load More: “Showing 40 of 156 products”
- Infinite scroll: “47 items loaded” (update as new content arrives)
Choosing the Right Pattern
| Factor | Pagination | Load More | Infinite Scroll |
|---|---|---|---|
| Footer reachable | Yes | Yes | No (without Ctrl+End) |
| Keyboard accessibility | Best | Good | Challenging |
| URL/bookmark support | Yes | Partial | No |
| Content position awareness | Best | Good | Poor |
| User control | Full | Good | None |
| Implementation complexity | Low | Medium | High |
| Best for | Search results, catalogs | Product listings, galleries | Social feeds, activity streams |
Testing
- Keyboard: Navigate the entire content list using Tab. Can you reach the footer? Can you reach all navigation?
- Focus after load: When new content loads, where does focus go? It should not jump to the top of the page.
- Screen reader: Navigate through items. Are positions announced? Is loading communicated? Can you escape the feed?
- Count accuracy: Do item counts update correctly as content loads?
- Apply testing methodology across browsers and assistive technologies.
Key Takeaways
Pagination is the most accessible content-loading pattern. “Load more” buttons provide a good middle ground with user control and reachable page elements. Infinite scroll is the least accessible and should only be used when the content model demands it (activity feeds), implemented with role="feed" and keyboard escape mechanisms. Whichever pattern you choose, communicate content position, manage focus after loading, and ensure the footer and page-level navigation remain reachable.
Sources
- W3C WAI-ARIA APG: Feed Pattern — The ARIA pattern for infinite scrolling content feeds.
- WCAG 2.2 SC 2.4.5 Multiple Ways — The requirement for multiple ways to locate content, relevant to pagination.
- WebAIM: Accessible Dynamic Content — Guidance on accessible dynamically loaded content.
- Nielsen Norman Group: Infinite Scrolling — Usability research on infinite scroll patterns.