Search code examples
reactjspaginationnavigationaccessibility

Pagination accessibility


What should be aria-label for link with dots in it? That indicates that there are more pages in between.

Do we still need to wrap everything in ul with li or following structure is fine?

<nav role='navigation'>
  <a href='page-1' aria-label='Goto page 1'>1</a>
  <a href='page-2' aria-label='Goto page 2'>2</a>
  <a href='page-3' aria-label='Goto page 3'>3</a>
  <a href='#' aria-label='...'>...</a>
  <a href='page-10' aria-label='Goto page 10'>10</a>
</nav>

Solution

  • My following answer is theoretical and I don’t have any insights from usability testing with screen reader users!

    In pagination, … serves as an ellipsis, contracting several pages, while always keeping the first and last page in the list, which communicates the total number of pages.

    Sometimes, this ellipsis is a link to the adjacent page, sometimes it’s not a link, for example in the Gov.uk Design System Pagination

    That’s the biggest error in the example code: The ellipsis is linked to #. It should either not be a link at all, or be linked to the adjacent page, in this case 4.

    Personally, I would recommend the link.

    ARIA labels

    It’s quite repetitive to listen to “go to page” for each page. It’s no different to showing that text visually: It’s simply noise.

    “Goto” is quite redundant for a link.

    “Page 1” would be sufficient, as the Gov.uk navigation does it. Simply 1, 2, 3 might suffice as well. The navigation’s name should probably convey that it’s a page navigation. It's likely not the only navigation on the page, so it should have a name anyway.

    A best practice is to have the text of the label at the start of the name.

    Understanding Success Criterion 2.5.3: Label in Name

    <nav aria-label="Results pages">
    …
    <a href="page-1">1</a>
    

    Conveying the total number of pages

    A list should be used so that a screen reader can announce the number of links available in the navigation.

    This will not correspond to the total number of pages. The ellipsis explains that visually and also to assistive technology.

    In tables and grids, ariarowcount` can be used to convey the total number of rows if they are not in the DOM. This attribute is disputed, though, and does not exist for lists.

    Since the ellipsis would be linking to page 4, it should simply labelled so.

    While the fact that it will render available another range of pages might be implicit in the lack of links between 4 and 10, you could add that to the accessible name:

    <a href="page-4" aria-label="4…">…</a>
    

    Another option is to simply not link page 4, as Gov.uk does.

    <li><a href="page-3">3</a></li>
    <li>…</li>
    <li><a href="page-10">10"</a></li>
    

    Mark the current page

    A pagination should also use aria-current to mark the current page.

    <a href="page-3" aria-current="page">3</a>
    

    So my total suggestion would be

    <nav aria-label="Results pages">
    <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" aria-label="4…">…</a></li>
      <li><a href="page-10">10</a></li>
    </ul>
    </nav>
    

    Why contract pages?

    The interest of contracting pages is based on the realisation that users’ interest declines (probably exponentially) after page 1. Users would probably rather change their search criteria or whatever brought them to the list, than proceeding to page 4. Screen real estate, especially on mobile, makes this even more interesting.

    Assuming that you can prioritize the list items, users are likely to find what they want close to the top. To focus users’ attention and improve response time, you can start by showing a fairly short list, and then offer pagination options for progressing further down the list if needed.

    https://www.nngroup.com/articles/item-list-view-all/