Skip to content

Pagination

Tier B. Follows the anatomy template and the conventions.

Moves between the pages of a long list or table. Renders a <nav> landmark named “Pagination” around a list of page controls: native <a href> links when each page has an address, or native <button>s when the application changes the page itself. The current page has aria-current="page". No APG pattern applies beyond the landmark, the list and the native controls.

A row of small keys, one per page shown, with a Previous and a Next key at the ends. The current page’s key is held down, like a latched ToggleButton.

Part Shape Height at 50% Moves
Page key radius.control, the density’s control height, at least as wide as it is high elevation.raised (3) Travels on press; the current page is held down
Previous, Next The same key with a chevron elevation.raised As a page key; flat and dimmed at the first or last page
Ellipsis “…” between keys, where pages are skipped Flat No
Face Colour role Text role Material role
Page key secondary text, tabular figures control (matte)
Current page accent on-accent, strong buttonPrimary
Ellipsis None muted None

The current page is shown by its fill, its weight and its key held down, never by colour alone.

State Relief Objects CSS
Rest Key at elevation.raised Key Relief recipe at raised
Hover Height × state.hoverHeight Key rises Larger shadow
Pressed Height × state.pressHeight Key travels Smaller shadow
Current (aria-current="page") Held at state.pressHeight, accent Key held down accent fill
Focus-visible outline: focus.width solid accent Same Same
Disabled (Previous at the first page, Next at the last) Height 0, chevron at 38% Flattened Flat, 38%

One raised primitive per key: each link or button, from its border box. At the Objects level each is a key, and the current page’s key is held at its travel (aria-current, as aria-pressed).

Token Prop
colour.secondary, colour.accent, colour.on-accent, colour.text, colour.muted —
radius.control, control.height, control.font, target.min, space.* size
elevation.raised, state.*, object.keyHeight, object.keyTravel —
material.roles.control, material.roles.buttonPrimary material
focus.width, focus.offset —
level level
<nav class="ug-pagination" aria-label="Pagination">
<ul class="ug-pagination__list">
<li class="ug-pagination__item"><a class="ug-pagination__link ug-pagination__link--previous" data-strata-face="raised" href="/items?page=3" aria-label="Previous page"></a></li>
<li class="ug-pagination__item"><a class="ug-pagination__link" data-strata-face="raised" href="/items?page=1" aria-label="Page 1">1</a></li>
<li class="ug-pagination__item" aria-hidden="true"><span class="ug-pagination__ellipsis">…</span></li>
<li class="ug-pagination__item"><a class="ug-pagination__link" data-strata-face="raised" href="/items?page=3" aria-label="Page 3">3</a></li>
<li class="ug-pagination__item"><a class="ug-pagination__link" data-strata-face="raised" href="/items?page=4" aria-label="Page 4" aria-current="page">4</a></li>
<li class="ug-pagination__item"><a class="ug-pagination__link" data-strata-face="raised" href="/items?page=5" aria-label="Page 5">5</a></li>
<li class="ug-pagination__item" aria-hidden="true"><span class="ug-pagination__ellipsis">…</span></li>
<li class="ug-pagination__item"><a class="ug-pagination__link" data-strata-face="raised" href="/items?page=10" aria-label="Page 10">10</a></li>
<li class="ug-pagination__item"><a class="ug-pagination__link ug-pagination__link--next" data-strata-face="raised" href="/items?page=5" aria-label="Next page"></a></li>
</ul>
</nav>
  • The <nav> is the boundary element: refs, class and style reach it. Its name defaults to “Pagination”.
  • Pages shown: the first and last pages, the current page and siblings (1) pages either side of it; a run of skipped pages is an ellipsis, hidden from assistive technology. With 7 pages or fewer (for 1 sibling) every page is shown.
  • Links or buttons: with an address per page (href), every key is a link; otherwise each is a <button type="button"> and the application changes the page (onPageChange). At the first page, Previous is a disabled button (or a link without href, with aria-disabled="true"); likewise Next at the last.
  • Names: “Page N”, which contains the visible number (WCAG 2.5.3); “Previous page” and “Next page” for the chevrons.
  • React and Vue: <Pagination page count onPageChange href siblings label> (Vue: v-model:page, and href a function). Astro: page, count and href, a template with {page} ("/items?page={page}").
  • No overlay.
Key Action
Tab, Shift+Tab Move between the keys (native order); a disabled Previous or Next is skipped
Enter (link or button), Space (button) Go to that page (native)
  • A navigation landmark named “Pagination” with a list of keys; the current page is announced as “Page 4, current page”.

A wrapping flex row with space.3 gaps, so the keys’ shadows do not touch. Keys use the raised recipe with secondary (the current page accent), centred tabular figures, and space.2 inline padding. The chevrons are drawn by two borders. Under forced-colors keys have a ButtonBorder border and the current page is Highlight with HighlightText.

  • Bindings: React, Vue and Astro render exactly the markup above; the pages shown for several positions; buttons change the page through onPageChange (v-model:page) with clicks and Enter; Previous and Next, and their disabled states at the ends; names and aria-current; axe in light and dark.
  • GPU: at Relief and Objects every page is a key and the current page’s key is held down (pressed); a real click on another page through the GPU moves it, with GPU on.