Exploring how to build an:

Accessible Pagination

Published on:

Last updated: Monday, October 24, 2016.

If you have a suggestion or an issue please submit it on a11ymatters on Github.

Article Outline

Summary

When there is a lot of content to display, using pagination will help us to add navigation links to reveal more content on the page.

As a user

  • As a user, I should be able to navigate by keyboard.
  • As a user, I should be able to know that there is a pagination navigation when scanning the page with a screen reader.
  • As a user, Each navigation item should be read as "Goto Page 1".
  • As a user, I need to know which element is currently active.
  • As a user, I need to navigation with Next and Previous links.

Ingredients

  • aria-label
  • aria-current
  • role=navigation
  • nav
  • links

Things to take in consideration

In order to let AT users recognize that there is a pagination, we should wrap the links in a <nav> element.

<nav>
    <ul>
        <!-- pagination links -->
    </ul>
</nav>

Also, we should add role=navigation and aria-label to make it clearer to AT users that this navigation landmark is intended for the pagination.

<nav role="navigation" aria-label="Pagination Navigation">
    <ul>
        <!-- pagination links -->
    </ul>
</nav>
<nav role="navigation" aria-label="Pagination Navigation">
    <ul>
        <li><a href="/page-1">1</a></li>
        <li><a href="/page-2">2</a></li>
        <li><a href="/page-3">3</a></li>
        <li><a href="/page-4">4</a></li>
        <li><a href="/page-5">5</a></li>
    </ul>
</nav>

For sighted users, it’s clear that the numbers will help him navigating different pages. But for an AT user, it’s completely different. We need a better way to make it clear for him.

See the below video for a test with VoiceOver:

Imagine that your screen is not working for some reason, you need to navigate between different pages. When you hear Link, 1 for a link with the number 1, do you think that you will get it? No! It’s not clear.

<nav role="navigation" aria-label="Pagination Navigation">
    <ul>
        <li><a href="/page-1" aria-label="Goto Page 1">1</a></li>
        <li><a href="/page-2" aria-label="Goto Page 2">2</a></li>
        <li><a href="/page-3" aria-label="Goto Page 3">3</a></li>
        <li><a href="/page-4" aria-label="Goto Page 4">4</a></li>
        <li><a href="/page-5" aria-label="Goto Page 5">5</a></li>
    </ul>
</nav>

By using aria-label, we can add a label to each link, so instead of hearing the screen reader saying Link, 1 it will be Link, Goto Page 1. See the below video:

To make it more dynamic, we will use JavaScript to loop through all the links and add aria-label with the corresponding value of “Goto Page X”.

3- Indicate which element is currently active

To indicate which element is active, we need to tweak the value of aria-label by something like Page 3, Current page. Also, we will use aria-selected=true for that.

Update: Using aria-selected is wrong in our case, because it should be used only with a role attribute. Instead, we will use aria-current. Thanks to David Storey and Stefan Judis for commenting about this. ❤️

<nav role="navigation" aria-label="Pagination Navigation">
    <ul>
        <!-- other pagination links -->
        <li>
          <a href="/page-3" aria-label="Current Page, Page 3" aria-current="true">3</a>
        </li>
        <!-- other pagination links -->
    </ul>
</nav>

Using JavaScript to dynamically add the aria-label

1
2
3
4
5
6
7
8
9
10
11
12
var pagItems = document.querySelectorAll('.pagination__item');

for (var i = 0; i < pagItems.length; i++) {
  var counter = i + 1;
  var string = "Page " + counter;

  if (pagItems[i].getAttribute('aria-current')) {
    string = "Page " + counter + ", Current Page";
  }

  pagItems[i].setAttribute('aria-label', string);
}

Line 1: Select all the pagination links and add them to an array.

Line 2: Loop through each item.

Line 7: Check if the item has an attribute of aria-current, if yes then we need to tweak the aria-label value.

Line 11: Add the attribute aria-label with a custom name for each item.

Final Demo

See the Pen a11ymatters - Pagination by Ahmad Shadeed (@shadeed) on CodePen.

Ahmad Shadeed

UI, UX Designer & Front-End Developer. Writing about web accessibility on @weba11ymatters and sharing articles on my blog. Interested in Modular Design, CSS Architecture and Layout Design.

More patterns

Share your thoughts and ideas: