Skip to Content
Component ExamplesInfinite Scroll

Overview

Infinite scroll automatically loads new content as the user scrolls down, removing the need to click a “next page” link. While convenient for mouse users, it creates severe accessibility barriers: keyboard users can never reach the page footer because new content keeps inserting before it, screen reader users have no sense of position or total items, and there is no explicit user action to trigger loading. The accessible alternative is a “Load More” button that gives users explicit control over when additional content appears.

WCAG Criteria:

Key requirements:

  • Never use infinite scroll as the sole mechanism for loading content — keyboard users may be unable to reach content beyond the scroll region
  • Provide a “Load More” button that explicitly loads the next batch of items
  • Use aria-live="polite" to announce how many items were loaded and the new total
  • Maintain focus on the “Load More” button after loading so the user keeps their place
  • Ensure page footer and other content below the list remain reachable at all times
  • Consider adding aria-setsize and aria-posinset on list items so screen readers can convey position (e.g., “item 3 of 12”)

Load More Pattern

Infinite Scroll vs. Explicit Load More Button

Inaccessible
<!-- Infinite scroll — no controls, footer unreachable, no announcements --> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> <p>Scroll to load more...</p> <!-- Footer is pushed down infinitely — keyboard users can never reach it --> <footer>Contact Us</footer>
Live Preview
  • Item 1
  • Item 2
  • Item 3

Scroll to load more...

Contact Us
Accessible
<ul id="item-list" role="list"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> <button onclick=" var list = document.getElementById('item-list'); var count = list.children.length; for (var i = 1; i <= 3; i++) { var li = document.createElement('li'); li.textContent = 'Item ' + (count + i); list.appendChild(li); } var total = list.children.length; var msg = document.getElementById('load-status'); msg.textContent = '3 more items loaded, ' + total + ' total'; this.focus(); "> Load More </button> <!-- Pre-existing live region announces the update politely --> <div id="load-status" role="status" aria-live="polite" style="position:absolute;width:1px;height:1px; overflow:hidden;clip:rect(0,0,0,0);"> </div> <!-- Footer is always reachable --> <footer>Contact Us</footer>
Live Preview
  • Item 1
  • Item 2
  • Item 3
Contact Us

What’s wrong with infinite scroll?

  • Keyboard users can never Tab past the list to reach the footer — new items keep loading as they navigate
  • Screen reader users have no sense of how many items exist or where they are in the set
  • There is no explicit action to trigger loading, so users cannot predict when new content will appear
  • The “Scroll to load more…” text is meaningless to screen readers and keyboard users
  • Content that appears without user action may confuse users with cognitive disabilities

What the screen reader announces:

VersionAnnouncement
Inaccessible (infinite scroll)“Item 1. Item 2. Item 3.” — no indication more items exist, footer unreachable
Accessible (Load More)“Item 1. Item 2. Item 3. Load More, button” — on click: “3 more items loaded, 6 total” (polite announcement)

Why “Load More” is better than infinite scroll:

  • The button gives the user explicit control over when content loads
  • Focus stays on the button after loading, so the user can continue loading or move past it
  • The aria-live="polite" region announces the result without interrupting the user
  • The footer and all content below the list remain reachable at all times
  • aria-setsize and aria-posinset can be added to list items to give screen readers exact position context (e.g., “item 3 of 12”)

Resources