Pagination
Links, for the same reason sortable headers are: a page of results is a URL. It can be shared, bookmarked, opened in a new tab and reached with the back button, and it works with scripting off.
Reference
sk-pagination
The current page is a <span> carrying aria-current, not a link to where you already are. Disabled ends are spans too - an anchor with no href is not focusable, and one that goes nowhere is worse than absent.
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">1-20 of 240</p>
<ul class="sk-pagination-list">
<li><a class="sk-page sk-page-step" href="?page=1" rel="prev">…</a></li>
<li><span class="sk-page" aria-current="page">2</span></li>
<li><span class="sk-page-gap" aria-hidden="true">…</span></li>
<li><a class="sk-page" href="?page=12" aria-label="Page 12">12</a></li>
</ul>
</nav>| Attribute | Type | Default | Notes |
|---|---|---|---|
aria-label | string | "Pagination" | A page with two paginated lists needs distinct labels, or a screen reader announces two identical landmarks. |
aria-current | "page" | - | On the current page only. |
data-disabled | "true" | - | On the previous/next step when there is nowhere to go. |
Around (Go) | int | 1 | Pages shown either side of the current one. A gap of exactly one page renders the page rather than an ellipsis - hiding it saves nothing and costs a click to find out. |
Examples
In the middle
Show markup
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
101-120 of 240
</p>
<ul class="sk-pagination-list">
<li>
<a class="sk-page sk-page-step" href="?page=5" rel="prev">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</a>
</li>
<li>
<a class="sk-page" href="?page=1" aria-label="Page 1">
1
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=5" aria-label="Page 5">
5
</a>
</li>
<li>
<span class="sk-page" aria-current="page">
6
</span>
</li>
<li>
<a class="sk-page" href="?page=7" aria-label="Page 7">
7
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=12" aria-label="Page 12">
12
</a>
</li>
<li>
<a class="sk-page sk-page-step" href="?page=7" rel="next">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</a>
</li>
</ul>
</nav>At the ends
Previous and next become non-focusable spans rather than dead links.
Show markup
<div class="sk-flex sk-flex-col sk-gap-4">
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
1-20 of 240
</p>
<ul class="sk-pagination-list">
<li>
<span class="sk-page sk-page-step" data-disabled="true" aria-hidden="true">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</span>
</li>
<li>
<span class="sk-page" aria-current="page">
1
</span>
</li>
<li>
<a class="sk-page" href="?page=2" aria-label="Page 2">
2
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=12" aria-label="Page 12">
12
</a>
</li>
<li>
<a class="sk-page sk-page-step" href="?page=2" rel="next">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</a>
</li>
</ul>
</nav>
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
221-240 of 240
</p>
<ul class="sk-pagination-list">
<li>
<a class="sk-page sk-page-step" href="?page=11" rel="prev">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</a>
</li>
<li>
<a class="sk-page" href="?page=1" aria-label="Page 1">
1
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=11" aria-label="Page 11">
11
</a>
</li>
<li>
<span class="sk-page" aria-current="page">
12
</span>
</li>
<li>
<span class="sk-page sk-page-step" data-disabled="true" aria-hidden="true">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
</li>
</ul>
</nav>
</div>Short lists
Below eight pages there is nothing to elide, so nothing is.
Show markup
<div class="sk-flex sk-flex-col sk-gap-4">
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
21-40 of 60
</p>
<ul class="sk-pagination-list">
<li>
<a class="sk-page sk-page-step" href="?page=1" rel="prev">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</a>
</li>
<li>
<a class="sk-page" href="?page=1" aria-label="Page 1">
1
</a>
</li>
<li>
<span class="sk-page" aria-current="page">
2
</span>
</li>
<li>
<a class="sk-page" href="?page=3" aria-label="Page 3">
3
</a>
</li>
<li>
<a class="sk-page sk-page-step" href="?page=3" rel="next">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</a>
</li>
</ul>
</nav>
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
1-12 of 12
</p>
<ul class="sk-pagination-list">
<li>
<span class="sk-page sk-page-step" data-disabled="true" aria-hidden="true">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</span>
</li>
<li>
<span class="sk-page" aria-current="page">
1
</span>
</li>
<li>
<span class="sk-page sk-page-step" data-disabled="true" aria-hidden="true">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
</li>
</ul>
</nav>
</div>Wider window
Around: 2.
Show markup
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
191-200 of 500
</p>
<ul class="sk-pagination-list">
<li>
<a class="sk-page sk-page-step" href="?page=19" rel="prev">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</a>
</li>
<li>
<a class="sk-page" href="?page=1" aria-label="Page 1">
1
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=18" aria-label="Page 18">
18
</a>
</li>
<li>
<a class="sk-page" href="?page=19" aria-label="Page 19">
19
</a>
</li>
<li>
<span class="sk-page" aria-current="page">
20
</span>
</li>
<li>
<a class="sk-page" href="?page=21" aria-label="Page 21">
21
</a>
</li>
<li>
<a class="sk-page" href="?page=22" aria-label="Page 22">
22
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=50" aria-label="Page 50">
50
</a>
</li>
<li>
<a class="sk-page sk-page-step" href="?page=21" rel="next">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</a>
</li>
</ul>
</nav>Under a table
| Name | Status | Balance |
|---|---|---|
| Ada Lovelace ada@example.com | Active | 1,240.00 |
| Grace Hopper grace@example.com | Active | 980.50 |
| Alan Turing alan@example.com | Pending | 111.11 |
| Katherine Johnson katherine@example.com | Failed | 17.00 |
| Edsger Dijkstra edsger@example.com | Archived | 2,006.75 |
Show markup
<div class="sk-flex sk-flex-col sk-gap-4">
<div class="sk-table-wrap">
<table class="sk-table" data-density="compact" data-hoverable="true">
<thead>
<tr>
<th scope="col">
Name
</th>
<th scope="col">
Status
</th>
<th scope="col" data-numeric="true">
Balance
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="sk-table-cell-stack">
<span>
Ada Lovelace
</span>
<span class="sk-table-cell-muted">
ada@example.com
</span>
</span>
</td>
<td>
<span class="sk-badge" data-status="success">
Active
</span>
</td>
<td data-numeric="true">
1,240.00
</td>
</tr>
<tr>
<td>
<span class="sk-table-cell-stack">
<span>
Grace Hopper
</span>
<span class="sk-table-cell-muted">
grace@example.com
</span>
</span>
</td>
<td>
<span class="sk-badge" data-status="success">
Active
</span>
</td>
<td data-numeric="true">
980.50
</td>
</tr>
<tr>
<td>
<span class="sk-table-cell-stack">
<span>
Alan Turing
</span>
<span class="sk-table-cell-muted">
alan@example.com
</span>
</span>
</td>
<td>
<span class="sk-badge" data-status="warning">
Pending
</span>
</td>
<td data-numeric="true">
111.11
</td>
</tr>
<tr>
<td>
<span class="sk-table-cell-stack">
<span>
Katherine Johnson
</span>
<span class="sk-table-cell-muted">
katherine@example.com
</span>
</span>
</td>
<td>
<span class="sk-badge" data-status="danger">
Failed
</span>
</td>
<td data-numeric="true">
17.00
</td>
</tr>
<tr>
<td>
<span class="sk-table-cell-stack">
<span>
Edsger Dijkstra
</span>
<span class="sk-table-cell-muted">
edsger@example.com
</span>
</span>
</td>
<td>
<span class="sk-badge" data-status="neutral">
Archived
</span>
</td>
<td data-numeric="true">
2,006.75
</td>
</tr>
</tbody>
</table>
</div>
<nav class="sk-pagination" aria-label="Pagination">
<p class="sk-pagination-info">
11-15 of 240
</p>
<ul class="sk-pagination-list">
<li>
<a class="sk-page sk-page-step" href="?page=2" rel="prev">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6">
</path>
</svg>
Previous
</a>
</li>
<li>
<a class="sk-page" href="?page=1" aria-label="Page 1">
1
</a>
</li>
<li>
<a class="sk-page" href="?page=2" aria-label="Page 2">
2
</a>
</li>
<li>
<span class="sk-page" aria-current="page">
3
</span>
</li>
<li>
<a class="sk-page" href="?page=4" aria-label="Page 4">
4
</a>
</li>
<li>
<span class="sk-page-gap" aria-hidden="true">
…
</span>
</li>
<li>
<a class="sk-page" href="?page=48" aria-label="Page 48">
48
</a>
</li>
<li>
<a class="sk-page sk-page-step" href="?page=4" rel="next">
Next
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</a>
</li>
</ul>
</nav>
</div>