Skip to main content
Pricing

Pagination

Free

Page-level navigation for traversing multi-page data sets. Displays numbered page buttons, previous/next arrows, and optional ellipsis for truncated ranges. Always communicates the current page and total pages to assistive technology.

6 variants

Variant
1
2
3
...
12

Variants

VariantDescriptionWhen to use
DefaultNumbered page buttons with previous/next arrows and ellipsis truncation.Use for paginated lists, tables, and search results with known page counts.
CompactSimplified pagination showing only previous/next buttons and "Page X of Y" text.Use in space-constrained contexts like mobile views or card footers.
With Input

Usage Guidelines

Do

Wrap in <nav aria-label="Pagination"> for landmark identification.

Don't

Use pagination for fewer than 2 pages — hide it when all results fit on one page.

Do

Mark the current page with aria-current="page".

Don't

Remove the current page indicator — users need to know where they are.

Do

Disable previous/next buttons at the bounds rather than hiding them.

Don't

Auto-paginate without user action — that pattern is infinite scroll.

Do

Show total page count or result count for orientation.

Don't

Use pagination for sequential content like articles — use previous/next links instead.

Code

HTML
<nav class="lex-pagination" aria-label="Pagination">
  <button class="lex-pagination__btn lex-pagination__btn--prev"
    aria-label="Previous page" disabled>
    <svg aria-hidden="true"><!-- chevron left --></svg>
  </button>
  <ol class="lex-pagination__list">
    <li><button class="lex-pagination__page" aria-current="page">1</button></li>
    <li><button class="lex-pagination__page">2</button></li>
    <li><button class="lex-pagination__page">3</button></li>
    <li><span class="lex-pagination__ellipsis" aria-hidden="true">…</span></li>
    <li><button class="lex-pagination__page">12</button></li>
  </ol>
  <button class="lex-pagination__btn lex-pagination__btn--next"
    aria-label="Next page">
    <svg aria-hidden="true"><!-- chevron right --></svg>
  </button>
</nav>
CSS Custom Properties
.lex-pagination {
  display: flex;
  align-items: center;
  gap: var(--lex-space-4);
}

.lex-pagination__list {
  display: flex;
  align-items: center;
  gap: var(--lex-space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}

.lex-pagination__page {
  min-width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--lex-radius-md);
  border: none;
  background: transparent;
  color: var(--lex-text-muted);
  font-size: var(--lex-font-size-sm);
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}

.lex-pagination__page:hover {
  background: var(--lex-bg-surface-hover);
  color: var(--lex-text-default);
}

.lex-pagination__page[aria-current="page"] {
  background: var(--lex-bg-brand);
  color: var(--lex-text-on-brand);
  font-weight: 600;
}

.lex-pagination__btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
React
// Using Lexicon CSS classes with React

export function ResultsPagination() {
  const [page, setPage] = useState(1);

  return (
    <Pagination
      currentPage={page}
      totalPages={12}
      onPageChange={setPage}
    />
  );
}

Design Tokens

TokenValue (dark)Value (light)CSS property
--lex-pagination-btn-sizesize
--lex-pagination-btn-bgbg
--lex-pagination-btn-active-bgbg
--lex-pagination-gapgap

Accessibility

  • Wrap in <nav aria-label="Pagination"> as a distinct navigation landmark.
  • Current page uses aria-current="page" for screen reader identification.
  • Previous/next buttons use descriptive aria-labels, not just arrow icons.
  • Ellipsis elements have aria-hidden="true" since they carry no semantic meaning.
  • Disabled buttons at bounds use the disabled attribute rather than aria-disabled for simplicity.

Keyboard Interactions

TabMoves focus through previous, page numbers, and next buttons.
Enter/SpaceActivates the focused page button.