Pagination
A row of page chips for moving through a long list or paginated view.
Basic
Wrap a list of .pagination__button in .pagination. Mark the current page with data-state="active" and aria-current="page". The active chip paints --st-highlight while hover paints the lighter --st-accent.
<nav aria-label="Page navigation">
<ul class="pagination">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>With icons
Drop an <svg> or <i> inside the chip. Icons sit at 1em so they scale with the chip's font size and stay on the label baseline.
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a class="pagination__button" href="#" aria-label="Previous">
<i data-lucide="chevron-left"></i>
<span>Previous</span>
</a>
</li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li>
<a class="pagination__button" href="#" aria-label="Next">
<span>Next</span>
<i data-lucide="chevron-right"></i>
</a>
</li>
</ul>
</nav>Disabled
Set aria-disabled="true" on the chip (or use <button disabled>) to gray it out and turn off pointer events. Drop the href too so screen readers don't announce it as a link. Use on the leading or trailing chip when the user is at the start or end of the range.
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<span class="pagination__button" aria-label="Previous" aria-disabled="true">
<i data-lucide="chevron-left"></i>
<span>Previous</span>
</span>
</li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">1</a></li>
<li><a class="pagination__button" href="#">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li>
<a class="pagination__button" href="#" aria-label="Next">
<span>Next</span>
<i data-lucide="chevron-right"></i>
</a>
</li>
</ul>
</nav>Ellipsis
Drop .pagination__ellipsis in for a truncation marker between page ranges. Takes the same chip footprint so the row rhythm holds, no hover, no focus.
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a class="pagination__button" href="#" aria-label="Previous">
<i data-lucide="chevron-left"></i>
</a>
</li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#">2</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">3</a></li>
<li><a class="pagination__button" href="#">4</a></li>
<li><a class="pagination__button" href="#">5</a></li>
<li><span class="pagination__ellipsis" aria-hidden="true">…</span></li>
<li><a class="pagination__button" href="#">12</a></li>
<li>
<a class="pagination__button" href="#" aria-label="Next">
<i data-lucide="chevron-right"></i>
</a>
</li>
</ul>
</nav>Sizes
Add .pagination--sm or .pagination--lg for compact or large chips. Heights match the button scale at 28 / 36 / 44 px under default density.
<div class="d-flex flex-column gap-4 w-100">
<nav aria-label="Small page navigation">
<ul class="pagination pagination--sm">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>
<nav aria-label="Default page navigation">
<ul class="pagination">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>
<nav aria-label="Large page navigation">
<ul class="pagination pagination--lg">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>
</div>Alignment
Add .pagination--center or .pagination--end to flip the row's justify-content. Default is start.
<div class="d-flex flex-column gap-4 w-100">
<nav aria-label="Centered page navigation">
<ul class="pagination pagination--center">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>
<nav aria-label="End-aligned page navigation">
<ul class="pagination pagination--end">
<li><a class="pagination__button" href="#">Previous</a></li>
<li><a class="pagination__button" href="#">1</a></li>
<li><a class="pagination__button" href="#" data-state="active" aria-current="page">2</a></li>
<li><a class="pagination__button" href="#">3</a></li>
<li><a class="pagination__button" href="#">Next</a></li>
</ul>
</nav>
</div>Customization
Sixteen variables retune .pagination without touching component CSS. Override on .pagination itself, on a parent scope, or on :root. The cascade scopes the change. Size modifiers --sm / --lg retune the chip height, padding, and font size in their own scope, so there are no per-size vars to maintain.
| Variable | Default | Use |
|---|---|---|
--pagination-gap |
calc(0.25rem * var(--st-density)) | Space between chips |
--pagination-margin-bottom |
0 | Trailing space below the row |
--pagination-font-size |
0.875rem | Chip text size |
--pagination-button-height |
calc(2.25rem * var(--st-density)) | Chip height (also doubles as min-width so single-glyph chips land as squares) |
--pagination-button-padding-x |
calc(0.75rem * var(--st-density)) | Chip horizontal padding (longer labels grow from this) |
--pagination-button-inner-gap |
0.375rem | Space between icon and label inside a chip |
--pagination-button-radius |
var(--st-radius) | Chip corner radius (set 9999px for pill chips) |
--pagination-button-bg |
transparent | Chip rest background |
--pagination-button-color |
var(--st-foreground) | Chip rest text color |
--pagination-button-border-color |
transparent | Chip border color (set var(--st-border) for outlined chips) |
--pagination-button-hover-bg |
var(--st-accent) | Hover background (interactive chips only) |
--pagination-button-hover-color |
var(--st-accent-foreground) | Hover text color |
--pagination-button-active-bg |
var(--st-highlight) | Current page background (data-state="active" / aria-current="page") |
--pagination-button-active-color |
var(--st-highlight-foreground) | Current page text color |
--pagination-button-disabled-color |
var(--st-muted-foreground) | Disabled / ellipsis text color |
--pagination-button-ring |
var(--st-ring) | Focus outline color |