Skip to content
Bugwise
Menu
UI Components

Pagination

Splits a long list into pages with Prev, Next and page numbers. Learn numbered pages vs "Load more" vs infinite scroll, why the page belongs in the URL, and the boundary bugs hiding on page 1, the last page and page 999.

35 min Navigation iOS · Android · Web Also called: Paging, Page numbers, Load more

You’re shopping for a tent. You scroll to the bottom of page 1, tap 2, and the first tent on page 2 is… the last tent from page 1. You open a promising one on page 3, press Back, and you’re on page 1 again. You give up and buy somewhere else.

Pagination looks like a row of small numbers. Underneath, it’s arithmetic (which items belong on page 3?), state (where was the user?) and boundaries (page 1, the last page, page 0, page 999). Those three are exactly where testers find bugs.

What is it?

PaginationPaginationSplitting a long list into pages that load one at a time.Open in glossary → splits a long list (products, search results, orders, transactions) into pages that load one at a time. The user moves with Previous / Next and page numbers. Pages keep each request small and fast, and give users a sense of where they are: page 5 of 16.

You’ll meet it in web shops and search results, bank transaction histories, admin tables, and in the API behind almost every list in a mobile app, even when the app hides it behind a “Load more” button or infinite scrollInfinite scrollLoading more items automatically when the user reaches the bottom of a list.Open in glossary →.

Anatomy

Numbered pagination on a web shop, page 5 of 16

  1. 1

    Result summary

    “Showing 81–100 of 312”. Tells users where they are. Must be right on the last page too.

  2. 2

    Previous

    Goes one page back. Disabled (or hidden) on page 1.

  3. 3

    Page number

    Jumps to that page. A link or button, at least 44×44 pt on touch screens.

  4. 4

    Current page

    Highlighted and marked with aria-current="page". Not just a color change.

  5. 5

    Ellipsis (…)

    Shows that pages are skipped. Not clickable, hidden from screen readers.

  6. 6

    Last page

    Lets users jump to the end. Its number must match the real number of pages.

  7. 7

    Next

    Goes one page forward. Disabled on the last page.

  8. 8

    Page size selector

    “Per page: 20 / 50 / 100”. Changing it must land on a page that exists.

Numbered pages, “Load more” or infinite scroll?

There are three common ways to reveal the rest of a long list. Each one is valid in the right place. Switch between them and try to reach the footer:

9:41

Tents & packs

  • Alpine Backpack€9.99
  • Breeze Backpack€46.99
  • Cedar Backpack€83.99
  • Dune Backpack€120.99
  • Ember Backpack€157.99
  • Fjord Backpack€14.99
  • Glacier Backpack€51.99
  • Harbor Backpack€88.99
Help · Contact us · Returns · Imprint

Numbered pages

Scroll down and use Prev / Next. The footer is right below the pager.

  • + You always know where you are (page 3 of 8)
  • + Page can live in the URL: share, refresh, Back
  • + Footer is always reachable
  • − Extra taps to see more
  • − Small targets on phones if done badly

Items on screen: 8 of 60 · page 1 of 8

PatternBest forWatch out for
Numbered pagesSearch results, shops, tables, anything users compare or come back toTiny targets on phones, wrong page math
“Load more” buttonMobile lists, product gridsLosing loaded items and position after Back
Infinite scrollSocial feeds, photo streams, “just browsing”Unreachable footer, no sense of position, memory, accessibility

Designs & variants

  • Full pager (web, desktop): ‹ 1 … 4 5 6 … 16 ›. Shows first, last, the current page and its neighbors, with an ellipsis for the gaps.
  • Compact pager (phones): ‹ Prev · Page 5 of 16 · Next ›. Fewer, bigger targets. Material and Apple’s guidelines don’t define a numbered pager; mobile apps usually prefer “Load more” or infinite scroll.
  • Prev / Next only: for feeds or cursor-based APIs where the total isn’t known.
  • With a page size selector: “Per page: 20 / 50 / 100”, common in tables and admin tools.
  • With a result summary: “Showing 81–100 of 312”. Small text, many bugs.

When to use it

  • Users need to find, compare and come back to items: shops, search results, statements, admin tables.
  • The list is long (hundreds or thousands of items) and loading everything would be slow.
  • The page should be shareable or bookmarkable (“look at page 3 of the sale”).
  • There is important content below the list: a footer, filters, contact details.

Good and bad uses

Short list, show it all

A settings screen with 14 options, or a cart with 6 items. Just show the list.

Pages for a handful of items

“Page 1 of 2” for 12 notifications. Users have to tap to see the last two, and gain nothing.

Infinite scroll for a feed

A photo feed users browse without a goal. Nobody needs to come back to “page 7”.

Infinite scroll on a shop with a footer

The Returns and Contact links in the footer run away every time the user scrolls toward them.

How good pagination behaves

The page lives in the URL

On the web, the current page (and page size, sort, filters) belongs in the address: a query parameterQuery parameterData in a URL after the ?, like ?q=mug&sort=price, often used to keep search and filter state.Open in glossary → like shop.example.com/products?page=3&size=20. That single decision makes Back, Refresh, bookmarks and shared links all work. If the URL never changes, Back from a product takes the user to page 1, and a refresh throws away their place.

In apps, the same idea applies: after opening an item and going back, the list must be exactly where it was: same page, same loaded items, same scroll position.

The math is right at every boundary

Page n shows items (n − 1) × size + 1 to n × size, but never more than the total. Classic boundary value analysisBoundary value analysisTesting values at and just around the edges of valid ranges, where bugs love to hide.Open in glossary → applies; test these pages every time:

PageWhat should happen
1Prev disabled. Items 1–20.
2Starts with item 21. Nothing from page 1 repeats.
Last (16)Next disabled. “Showing 301–312 of 312”. Only 12 items.
0, −1, abcRedirect to page 1 (or a clear error). Never a crash.
999A helpful “This page doesn’t exist” with a link to the last page. Not an endless spinner.

Also check the edges of the data, not just of the pager: 0 results (an empty state, no pager), exactly one page (no pager, or both arrows disabled), exactly 20 items with 20 per page (one page, not two with an empty second one), and a last page with exactly one item.

Changing the page size lands somewhere sensible

On page 8 with 20 per page, the user switches to 50 per page. There are now only 7 pages, so “page 8” doesn’t exist. Good apps go back to page 1, or better, to the page that contains the item the user was looking at (item 141 → page 3). Same rule when a filter reduces the results: never leave the user on a page that no longer exists.

Data that changes between pages

Lists aren’t frozen. While you read page 1, new listings get posted and others sell out. With offset pagination (“skip 20, take 20”), that shifts everything: you see duplicates when items are added, and miss items when items are removed. Cursor pagination (“20 items after item X”) largely avoids it, because each page starts right after the last item you actually received. Try both:

Page 1 (what you saw)

newest first

  1. City bike
  2. Desk chair
  3. Coffee grinder
  4. Guitar

Since then: 0 new, 0 removed

Change the data with the buttons above, then press “Next page”.

As a tester you can’t choose the strategy, but you can find the bug: open page 1, have someone (or an admin tool, or a second device) add or delete items, then go to page 2. Report duplicates and missing items with the exact items involved.

Common bugs

#BugWhat you seeTypical severity
1Off-by-one offsetLast item of page 1 repeats on page 2, or one item is never shownHigh
2Wrong result summary“Showing 301–320 of 312” on the last pageLow
3Next enabled on the last pageLeads to an empty page or an errorMedium
4Out-of-range page?page=999 shows an endless spinner, a crash or a blank pageMedium
5Page size change keeps the pagePage 8 of 7: an empty listMedium
6Page not in the URLBack, refresh or a shared link always open page 1Medium–High
7Duplicates or gaps after data changesThe same item twice, or items missing across pagesMedium
8Wrong total“16 pages” but page 16 is empty, or the count ignores a filterMedium
9Tiny targets on phones24 px page numbers, users hit 4 instead of 5Medium
10Filters/sort reset when pagingPage 2 shows unsorted, unfiltered resultsHigh

Stress-test it

A correct pager on a correct list. The page and page size are in the URL. Try the browser Back and Reload buttons, type ?page=999, ?page=0 or ?page=abc in the address, switch Results to 0 or 7, and change Per page while you’re on the last page.

Results
Per page
Layout

Outdoor gear

HTTP 200 OK

Showing 1–20 of 312

  • #1Alpine Backpack€9.99
  • #2Breeze Backpack€46.99
  • #3Cedar Backpack€83.99
  • #4Dune Backpack€120.99
  • #5Ember Backpack€157.99
  • #6Fjord Backpack€14.99
  • #7Glacier Backpack€51.99
  • #8Harbor Backpack€88.99
  • #9Indigo Backpack€125.99
  • #10Juniper Backpack€162.99
  • #11Kestrel Backpack€19.99
  • #12Lagoon Backpack€56.99
  • #13Maple Backpack€93.99
  • #14Nova Backpack€130.99
  • #15Onyx Backpack€167.99
  • #16Pine Backpack€24.99
  • #17Quartz Backpack€61.99
  • #18Ridge Backpack€98.99
  • #19Sierra Backpack€135.99
  • #20Tundra Backpack€172.99

Screen reader on the pager

“Pagination, navigation” … “Page 1, current page, button”

Try these

  • Go to page 3, then browser Back and Reload
  • Type ?page=999, ?page=0 or ?page=abc
  • Open the last page, then switch Per page to 50

Find the bug

This web shop lists 312 products, 20 per page, and has six bugs. Explore it like a tester:

  • Compare the last product on page 1 with the first one on page 2.
  • Go to the last page (16) and read everything on it. Then look at the arrows.
  • Use the links panel: a bookmark to ?page=3 and an old link to ?page=999. Watch the Network log.
  • Go to page 8 and change Per page.
  • Go to page 3, open a product, then use the browser’s Back (and try Reload).

🐞 Bug hunt: Outdoor gear list

This demo has 6 hidden bugs. Explore it like a tester, then check your findings.

Found0/6

Loading products…

Links from emails & bookmarks

Network

  • API requests appear here…
  1. 1

    Hint: Note the last product on page 1, then go to page 2.

  2. 2

    Hint: Go to page 16 and read the text under the title.

  3. 3

    Hint: On page 16, look at the › arrow and tap it.

  4. 4

    Hint: Open the shop.example.com/products?page=999 link and wait. Check the Network log.

  5. 5

    Hint: Go to page 8, then set Per page to 50 or 100.

  6. 6

    Hint: Go to page 3, open a product, press the browser Back button.

How to test it

Checklist

Pagination test checklist

0 of 14 checked

Example test cases

TC-PAG-001No duplicates between page 1 and page 2

Preconditions

  • 312 products, 20 per page
  • Sorted by "Newest"

Steps

  1. Open the product list
  2. Note the last product on page 1
  3. Go to page 2

Expected result

Page 2 starts with product 21. The last product of page 1 does not appear on page 2.

TC-PAG-002Last page boundaries

Preconditions

  • 312 products, 20 per page

Steps

  1. Go to page 16

Expected result

12 products are shown, the summary says "Showing 301–312 of 312", Next is disabled.

TC-PAG-003Page survives Back and refresh

Steps

  1. Go to page 3
  2. Open any product
  3. Press the browser Back button
  4. Refresh the page

Expected result

Both times the list shows page 3 and the URL contains ?page=3.

TC-PAG-004Page number beyond the last page

Steps

  1. Open shop.example.com/products?page=999

Expected result

A message explains the page does not exist and offers a link to the last page (16). No endless spinner. The server responds 404 (or redirects).

TC-PAG-005Invalid page values

Steps

  1. Open ?page=0
  2. Open ?page=-1
  3. Open ?page=abc
  4. Open ?page=2.5

Test data

page = 0, -1, abc, 2.5

Expected result

Each URL redirects to page 1 or shows a clear error. No crash, no empty list, no "Showing -19–0".

TC-PAG-006Changing page size on a late page

Steps

  1. Go to page 8 (20 per page)
  2. Change Per page to 50

Expected result

The list shows an existing page (page 3, containing item 141, or page 1). The URL and summary are updated.

TC-PAG-007Filter and sort are kept across pages

Steps

  1. Filter by "Tents" and sort by "Price: low to high"
  2. Go to page 2 and page 3

Expected result

Every page only shows tents, prices keep increasing across pages, and the filter chips stay selected.

TC-PAG-008Screen reader announces the current page

Steps

  1. Turn on VoiceOver or NVDA
  2. Navigate to the pager by landmarks
  3. Move to the current page number

Expected result

The pager is announced as a "Pagination" navigation landmark and the current page as "Page 3, current page". The ellipsis is not read.

Tip: click a test case to expand it.

Tools

  • The URL bar is your best tool: edit ?page= and ?size= by hand to hit every boundary in seconds.
  • DevTools › Network (see DevTools for testers): filter by the API path and check page, offset, limit or cursor for each click. An offset=19 on page 2 is a bug you can prove.
  • API directly (Postman): request the last page, page=0, a negative page and a huge page; check status codes and the total field.
  • Mobile apps: use a proxy tool (Charles, Proxyman) to see the paging requests behind “Load more” and infinite scroll.

Accessibility

Mobile vs web

  • No native numbered pager. Lists usually load the next page when the user nears the end (infinite scroll) or show a Load more row.
    Dev note
    UITableView, SwiftUI List.
  • Test on a slow network: is there a loading row at the bottom? What happens if loading fails: a Retry button, or a silent dead end?
  • Pull to refresh while on “page 3” of loaded items: does the list reset cleanly without duplicates?
  • Open an item, go back: the list must keep every loaded item and the scroll position.
  • Lists usually load pages as you scroll.
    Dev note
    RecyclerView with the Paging library, or a LazyColumn in Compose.
  • Check rotation and process death (Developer options › Don’t keep activities): does the list come back on the same position, or restart from the top?
  • Fast scrolling (“fling”) through hundreds of items: watch for duplicates, gaps, placeholders that never fill and jumps in position.
  • Use airplane mode mid-scroll: a clear error row with Retry, not an endless spinner.
  • Numbered pagination is most common here. The page must be in the URL: test Back, Forward, Refresh, bookmarks and shared links.
  • Edit the URL by hand: ?page=0, ?page=999, ?page=abc, ?size=10000 (does the server cap the size?).
  • Check the responsive layout: at 360 px, does the pager wrap neatly, switch to a compact version, or overflow the page?
  • Search engines index paginated pages: every page should have its own URL and return 200; non-existent pages should return 404, not an empty 200 page.

Check your understanding

Quick quiz

0/6 answered · 0 correct

  1. 1.The last product on page 1 is also the first product on page 2. What is the most likely cause?

  2. 2.There are 312 products and 20 per page. What should the summary say on the last page?

  3. 3.A user goes to page 3, opens a product and presses Back. They land on page 1. What is the root cause most likely to be?

  4. 4.Which pattern makes the footer (Help, Contact) hard or impossible to reach?

  5. 5.You are on page 8 (20 per page, 312 items) and switch to 50 per page. What is a good result?

  6. 6.Which attribute tells screen reader users which page they are on?

Key takeaways

  • Pagination is math, state and boundaries. Always compare the last item of one page with the first of the next.
  • Test page 1, page 2, the last page, page 0, page 999 and invalid values like abc.
  • The page belongs in the URL so Back, refresh and shared links work. In apps, the list must keep its place after going back.
  • Changing the page size, sort or filters must never leave the user on a page that doesn’t exist.
  • Data that changes between page loads causes duplicates and gaps with offset paging.
  • Choose the pattern on purpose: numbered pages to find and return, Load more for mobile lists, infinite scroll for feeds only.
  • Accessibility: a nav landmark, aria-current="page", real links or buttons, and 44 pt / 48 dp touch targets.

Finished this page?Nice work, this page is complete!

Mark it as done to track your progress. It's saved in this browser, no account needed.

Its review cards are now in Bites ⚡
Esc

Type to search the whole site.