Skip to content

COMPONENT

Pagination

Where you are in a sequence of pages, and how to leave it. For an archive, an index, anything long enough that one page would be a scroll nobody finishes.

In the middle of a run

The current page, its neighbours, an elision, and the last page always within reach.

HTML
<nav class="pagination" aria-label="Pagination">
  <a class="pagination-step" href="#" rel="prev" aria-label="Previous">β€Ή</a>
  <a class="pagination-page" href="#">1</a>
  <a class="pagination-page" href="#" aria-current="page">2</a>
  <a class="pagination-page" href="#">3</a>
  <span class="pagination-gap" aria-hidden="true">…</span>
  <a class="pagination-page" href="#">9</a>
  <a class="pagination-step" href="#" rel="next" aria-label="Next">β€Ί</a>
</nav>

At an end

Page one. Previous is dimmed and still there β€” put a cursor on it, then tab through the row.

HTML
<nav class="pagination" aria-label="Pagination, on the first page">
  <span class="pagination-step" aria-disabled="true" aria-label="Previous">β€Ή</span>
  <a class="pagination-page" href="#" aria-current="page">1</a>
  <a class="pagination-page" href="#">2</a>
  <a class="pagination-page" href="#">3</a>
  <a class="pagination-step" href="#" rel="next" aria-label="Next">β€Ί</a>
</nav>

Reference

Read from components/pagination.css when this page was built, so it cannot fall behind the stylesheet.

CLASSES.pagination.pagination-page.pagination-step.pagination-gap
READS--ds-focus-ring--ds-font-display--ds-gap-tight--ds-hairline--ds-hit-min--ds-ink--ds-ink-disabled--ds-ink-faint--ds-ink-soft--ds-pad-chip--ds-radius-control--ds-raised--ds-rule--ds-rule-strong--ds-sunk--ds-text-ui--ds-track-subtle

Notes

SEPARATE TARGETS, NOT A JOINED BAR

This and .segmented look alike and answer different questions. A segmented control asks which variant, where every option is equally available and the set is closed. Pagination asks where am I in a sequence, where the neighbours matter and the ends run out. Joining these into one bar would say the wrong thing about the middle.

AN END IS INERT, NEVER MISSING

On the first page, previous is dimmed and stays where it is. Removing it shifts every remaining target sideways between one page and the next, so the control moves under a cursor already travelling towards it β€” and the reader loses the shape they had just learned.

THE ELISION IS NOT A TARGET

.pagination-gap stands for pages nobody listed. It is a span and it is aria-hidden: a screen reader announcing "ellipsis" between two numbers is noise, and a focusable one is a target that goes nowhere.

IT WRAPS, AND THAT IS THE 200px FLOOR

Ten numbers do not fit a 200px column. Wrapping keeps every page reachable; a sideways scroll would hide the last one behind a gesture nobody knows is there.