Pagination
Split long lists into pages or progressive loads in a way that keeps position, counts and selection predictable.
5 states4 edge casesDesktop + Mobile
01The problem
Large lists can't load all at once. The choice between page numbers, Load more and infinite scroll changes how users find things, share positions and come back. Infinite scroll on a work table breaks the footer, Back button and “where was I?”. Page numbers on a social feed feel bureaucratic.
02When to use
Use when
- Any list or table with more records than load quickly in one request
- Admin tables, search results, activity feeds
Avoid when
- Lists under ~100 items — load them all and let users filter.
03Recommended UX
Statecraft recommendation
Use numbered pages for work tables where users compare, select and return to positions; use Load more for feeds and search results where users mainly scan forward. Avoid pure infinite scroll in work tools. Always show the total or range, and keep the page in the URL.
Numbered pages give stable positions (“it's on page 3”), predictable footers, and working Back navigation.
Load more keeps users in control of loading and preserves access to the footer, unlike automatic infinite scroll.
“51–100 of 1,284” tells users how big the set is, which shapes whether they filter or browse.
04Interaction flow
- 01
First page loads
Range and total shown.
- 02
Navigate
Next/previous, page number, or Load more.
- 03
Position kept
Page in URL; scroll to top of table on page change.
- 04
Change page size or filters
Return to page 1.
Result
- Found item
- Reached end
05Desktop behaviour
On desktop, work tables use a compact footer with range, page size and page controls.
Desktop rules
- Footer: “51–100 of 1,284”, page size selector, Previous / page numbers / Next.
- Scroll to the top of the table, not the page, when changing pages.
- Keep row selection across pages and show the total selected.
- Disable Previous on the first page and Next on the last, but keep them visible.
06Mobile behaviour
On mobile, page number controls are fiddly. Use Load more with a clear count instead.
Mobile rules
- “Show 50 more · 1,184 remaining” button at the end of the list.
- Keep loaded items when returning from a detail view.
- Show “You've reached the end” on the last page.
07States
First page
Previous disabled; range shown.
Middle page
All controls enabled.
Loading page
Previous rows dimmed; controls disabled briefly.
Last page
Next disabled; “End of results”.
Out of range
Requested page no longer exists; show the last page with a notice.
08Edge cases
EC-01
Data changes between pages
New records are added while the user pages through, shifting rows.
Recommendation
Use cursor-based pagination for live data so items aren't skipped or duplicated.
EC-02
Deep link to a page that no longer exists
A shared link points to page 12, but filters now give 8 pages.
Recommendation
Show page 8 with a notice rather than an empty page.
EC-03
Exact totals are expensive
Counting 4 million rows is slow.
Recommendation
Show “1,000+” or an estimate, and keep Next/Previous working without the exact count.
EC-04
Selection across pages
The user selects rows on pages 1 and 3.
Recommendation
Persist by ID and show the total selected in the toolbar, with “Show selected”.
09Microcopy
Range
Avoid
“Page 2”
Prefer
“51–100 of 1,284”
Load more
Avoid
“More”
Prefer
“Show 50 more · 1,184 remaining”
End
Prefer
“You’ve reached the end · 1,284 invoices”
Estimate
Prefer
“1,000+ results”
10Accessibility
- Wrap controls in nav aria-label="Pagination" and mark the current page with aria-current="page".
- After a page change, move focus to the table heading or first row and announce the new range.
- Load more announces how many items were added.
11Developer notes
- 01
Prefer cursor pagination for live or large datasets; offset is fine for small, stable ones.
- 02
Store page, page size and cursor in the URL.
- 03
Prefetch the next page on idle for instant navigation.
12Implementation prompt
For Claude Code, Codex or Cursor
Implement pagination for the existing tables and lists.
Requirements:
- Work tables: footer with range ("51–100 of 1,284"), page size selector, Previous / numbered pages / Next.
- Feeds and search results on mobile: Load more with remaining count and an end-of-list message.
- Page, size and cursor in the URL; Back restores position.
- Cursor pagination for live data; estimates when totals are expensive.
- Reset to page 1 when filters or page size change; out-of-range pages fall back to the last page with a notice.
- Selection persists across pages by ID.
- Scroll to table top on page change; focus and announce the new range.
- Prefetch next page.
Do not redesign the existing interface.