Skip to main content
WCAGrules
Quick navigation

Guides · Interface patterns

Infinite Scroll Puts the Footer Out of Reach

A pattern that works well with a thumb and badly with almost everything else.

Last reviewed August 30, 2026

Infinite scroll loads more content as you approach the bottom of a list. For a mouse or a thumb that barely registers. For a keyboard user, a screen reader user, or anybody who came for something in the footer, it creates problems that are unusually hard to solve once the pattern is in place.

Before the problems, the thing almost nobody publishes. W3C has a design pattern for this exact widget, and it exists because infinite scroll creates usability and interoperability difficulties for assistive technology users. It is worth knowing about even if you decide against it, because every fix below has a counterpart in it.

There Is a Pattern For This, and It Is Called a Feed

The feed pattern establishes a contract between your page and the screen reader, so somebody can read and trigger the loading of more content while staying in their normal reading mode. That last part is the whole idea. A feed is a structure rather than a widget, which is what lets a screen reader keep its reading cursor working instead of switching into the application mode where the reading keys stop doing anything. That switch is the real reason infinite scroll is hard with a keyboard, and it is a better answer than calling it hard.

  • role="feed" on the container, with a label, and role="article" on each unit of content, each with its own label pointing at something inside it that identifies it.
  • aria-posinset and aria-setsize on each article, so somebody hears where they are in the set. aria-setsize can be the number loaded so far, or the total, or -1 where the total is genuinely undetermined, which is most feeds and is the case our old advice had no answer for.
  • aria-describedby on each article, strongly recommended, pointing at the primary content, so somebody can move article to article and judge which ones are worth stopping on.
  • aria-busy="true" while a batch is being added, then false when it is done. The pattern calls this extremely important, and it is the mechanism that stops a multi-step DOM update announcing itself in pieces.
  • Keyboard conventions, offered as conventions. Page Down for the next article, Page Up for the previous, Control and End to move to the first focusable element after the feed, Control and Home to move to the first one before it. W3C acknowledges that no convention is established here, so these are a proposal rather than behavior anybody will expect.

One honest caveat before you build on it. Browser and screen reader support for role="feed" is uneven, and we have not tested it ourselves across the pairs that matter. A pattern that is not supported in practice is worse advice than a live region that is, so treat this as the direction to move in and verify it against your own audience before you rely on it.

The Footer Problem

Content loads faster than a keyboard user can reach the bottom, so the footer moves away every time it comes close. Contact details, terms, the accessibility statement, all become effectively unreachable by the route people expect to use.

The feed pattern's Control and End binding is, on paper, exactly the fix for this, because it moves focus to the first focusable element after the feed. Whether a given screen reader implements it is the open question. Until that is settled, the reliable answers are the blunt ones. Stop loading automatically after a few batches. Duplicate the essential footer links somewhere that does not move. Or use a different pattern.

Tabbing through an endlessly growing list to reach anything past it is not a usable route, and it is a usability obligation rather than a WCAG one, because 2.4.1 Bypass Blocks is scoped to content repeated across pages and does not reach a single page's own feed. If the content past the list can be reached at all, with enough presses, the keyboard rule is satisfied and the problem is that nobody would.

Whatever route you take, give people something to jump with. A heading before the feed, a landmark around it, a way to collapse it, or a link that moves focus past it. Any of those is worth more than none, and a skip link does not have to be permanently visible. It may be hidden until it receives keyboard focus, which is what removes the usual design objection to one.

Announce the Count, Not the Arrival

Here is a distinction we had slightly wrong. New items appearing is not itself a status message. W3C says directly that a list of results is not a status update, and that the brief message about it is. So 20 more results loaded, 60 of 340 shown, is the thing 4.1.3 covers, and the sixty new cards are not.

The criterion also does not force you to invent messages. Its stated purpose is to make the messages you do display reachable, so a feed that shows no loading text and no count passes it without doing anything and still leaves a screen reader user with no idea whether anything happened. That is why what follows is advice rather than a requirement, and it is the advice that makes the pattern usable.

  • Announce once, with a number. One message telling somebody where they are beats a start and a finish that carry nothing between them.
  • Set aria-atomic="true" on the region. Without it, a region where only the number changes announces sixty, and a listener has no idea sixty of what. This is the attribute that decides whether your carefully written sentence arrives as a sentence.
  • Consider role="log" rather than role="status". A log region appends and a status region replaces, and an accumulating feed is exactly the case a log was defined for.
  • Use aria-busy while the batch lands, rather than hand-tuning what fires when. That is the standards answer to a loading message followed by a loaded message, which is two interruptions carrying no information between them.

Keep the Reader Where They Were

Focus has to stay put when new items load. Appending content should never move anybody, and a scroll position that resets on load is the most frustrating version of this bug.

The implementation detail behind that is worth naming, because it is the thing to build rather than the thing to hope for. The feed pattern divides the work explicitly. The page is responsible for scrolling appropriately based on which article holds focus, and for loading or removing articles based on which article holds focus. So the load trigger should be aware of where focus is, not only of where the scrollbar is. A trigger watching scroll position alone is what yanks a keyboard user around.

Load More Is Usually Better

A button that loads the next batch solves nearly every problem above at once. People get real control, it is keyboard reachable by default, it gives you a natural place to move focus, and the footer stays where it was put.

PatternFooter reachableKeyboardDeep linking
Infinite scrollNoHard, because a feed built as a widget pushes the reader out of reading modeHard
Load more buttonYesStraightforwardPossible
PaginationYesStraightforwardFree
Three patterns compared

That last column is worth more than it looks, and it connects to a rule. 2.4.5 Multiple Ways at Level AA asks for more than one route to a page, and a URL that identifies a position is part of how somebody gets back to one. Pagination gives you that for nothing, which is one of the quieter arguments for it.

After the button loads a batch, move focus to the first new item rather than leaving it on the button, so a keyboard user does not tab back through everything they already read. And remember what that choice does to the rest of the page. Moving focus is a change of context, which takes the update out of the status message rule, so a button that moves focus needs no live region and adding one announces the batch twice.

If You Keep Infinite Scroll

  1. Stop loading automatically after two or three batches and switch to a button.
  2. Announce the running count through a polite live region, atomic, once per batch.
  3. Give the list a heading and something to jump past it with, whether that is a landmark, a collapse control, or a link hidden until it is focused.
  4. Keep the browser URL updated so a position can be shared and returned to.
  5. Duplicate the essential footer links somewhere that does not move.

Common questions

Does infinite scroll fail WCAG outright?
Not as a pattern. It fails when new content is never announced, when focus or scroll position moves under the reader, or when it makes content genuinely unreachable. Each of those is fixable, so it is a difficulty rather than a prohibition. The footer problem in particular is a usability obligation rather than a criterion, because the bypass rule is scoped to content repeated across pages and does not reach one page's own feed.
What should an infinite feed announce?
The count, not the arrival. W3C says a list of results is not a status update and that the brief message about it is, so 20 more results loaded, 60 of 340 shown is the thing to say. Set aria-atomic to true or the region announces only the number that changed. Where the total is genuinely unknown, the feed pattern allows a set size of minus one rather than making you invent a denominator.
Is there a standard way to build this?
Yes, and it is not widely known. W3C publishes a feed pattern with roles for the container and each item, position and set size on every article, and a busy state while a batch loads. It also proposes keyboard conventions, including one that moves focus past the whole feed, while acknowledging that no convention is established. Support across browsers and screen readers is uneven, so verify it before you rely on it.
What about a hybrid, scrolling then a button?
That is the pragmatic answer. Load two or three batches automatically, then require a button. You keep the easy feel for the first screen or two and you stop the list growing without limit under somebody who is trying to reach the end of it.

Sources

Keep reading

More on interface patterns

Reading about it is the cheap part.

Find out where your site actually stands. The free scan checks 10 pages in a real browser against all 90 supported automated rules, keeps its 27 best-practice checks separate from WCAG findings, and names the rule behind every finding. The full audit adds an expert review and a real blind screen-reader user. From $499, with the report in 5 business days on Rapid and 10 on Standard, and the clock starting at cleared payment.

Go somewhere useful

Find tools, resources and your workspace.

29 destinations