SaaS Pagination & Infinite Scroll UX: Examples & Patterns (2026)
Every SaaS product eventually shows a list too long to fit on one screen — a table of thousands of contacts, an activity feed that never ends, search results, a log stream. How you let people move through that data is one of the most consequential and most overlooked UX decisions in the product. This guide covers the three core patterns — classic pagination, infinite scroll, and load-more — when each one fits, the failure modes of infinite scroll, how to preserve a user’s place and context, how loading and performance shape the feel, and how paging interacts with filtering, sorting, and bulk selection, each shown with real SaaS screenshots instead of mockups.
Every SaaS product eventually outgrows a single screen of data. A CRM accumulates tens of thousands of contacts, a project tool piles up years of tasks, an analytics product streams an endless log, a marketplace returns hundreds of search results. At that point you have to answer a deceptively small question: how does a person move through a list that is far too long to show all at once? The answer shapes how fast the product feels, whether users can find and return to what they need, and how much of the underlying data they can actually reach. It is one of the highest-leverage UX decisions in the product and one of the most casually made — usually defaulted to whatever the component library shipped rather than chosen for the task.
There is no single right answer, because "moving through a long list" is really several different jobs. Someone hunting for one specific record needs to navigate precisely and jump around; someone browsing a feed for whatever is new needs an effortless downward flow; someone auditing every row in a report needs a reliable way to cover the whole set without losing their place. The three dominant patterns — classic pagination, infinite scroll, and an explicit load-more button — each serve some of those jobs well and others badly. This guide walks through when each fits, the specific ways infinite scroll goes wrong, and the details that separate a list users trust from one they fight, each illustrated with real SaaS screenshots so you can see how shipped products handle it.
Match the pattern to the task, not the trend
The most important decision is choosing the right mechanism for what people are actually doing on the screen, rather than reaching for whichever pattern feels modern. Classic pagination — numbered pages with next and previous — is the right default for data people navigate deliberately: tables of records, admin lists, search results, anything where a user might need to find a specific item, know how far through they are, return to "page 3" tomorrow, or reason about the total size of the set. Infinite scroll suits open-ended, discovery-oriented feeds where the goal is continuous consumption and there is no meaningful "position" to hold onto — activity streams, notification lists, social-style timelines. The load-more button sits in between: it keeps the effortless single-column flow of infinite scroll but hands control back to the user, loading the next batch only when they ask, which avoids many of infinite scroll’s worst side effects. Start from the user’s goal — precise retrieval, casual browsing, or exhaustive review — and the pattern usually chooses itself.
Where infinite scroll quietly hurts
Infinite scroll feels effortless in a demo and causes real, specific problems in a product, which is why it is the pattern most often applied where it does not belong. The first casualty is the footer: any links, settings, or summary that live below the list become permanently unreachable because new content keeps loading before the user can get there. The second is orientation — an infinite list gives no sense of scale or position, so a user cannot tell whether they have seen ten items or ten thousand, or how much remains. The third, and most damaging in productivity software, is losing your place: a user scrolls deep into a list, clicks into an item, hits back, and lands at the top of a re-loaded list with their scroll position and loaded batches gone, forced to scroll all the way down again. Deep-linking and sharing break for the same reason — there is no "page 4" to bookmark or send to a colleague. None of these are edge cases; they are the everyday cost of applying a browsing pattern to data people need to navigate and return to.
If you do use infinite scroll, engineer around its failures
When infinite scroll genuinely fits — a consumption feed with no stable position — it still needs deliberate engineering to be humane. Preserve and restore scroll position and already-loaded batches when the user navigates away and comes back, so returning from a detail view does not dump them at the top of a fresh list. Reflect the current position in the URL where you can, so a state is at least partially shareable and the back button behaves. Keep any footer content out of the infinitely-growing column — move it to a sidebar or a persistent bar — so it never becomes a moving target. And give the stream a clear, honest end state when the data actually runs out, rather than an eternal spinner that implies more is coming. Infinite scroll is not free; if you choose it, budget for the work that makes it not hurt.
Design pagination controls that respect the user
Classic pagination earns its keep only if the controls are actually usable, and a surprising number ship half-built. Give users more than blind next and previous: show numbered pages so they can jump, and for very large sets a way to jump to the first, last, or an arbitrary page rather than clicking "next" forty times. Show where they are and how big the set is — "Page 3 of 47" or "Showing 51–75 of 1,182" turns an opaque list into something a person can reason about and plan against. Let users control page size where it matters, because the right number of rows per page for a quick scan differs from the right number for exhaustive review. Keep the current page, page size, and sort in the URL so the view is bookmarkable, shareable, and survives a refresh or a back-button press. And make the controls reachable without a marathon scroll — a bottom bar is standard, but for long tables a sticky control or a top-and-bottom pairing saves real effort.
Preserve place and context across navigation
The single behavior that most separates a trusted list from a frustrating one is what happens when a user leaves and returns. People do not consume a long list in one pass — they drill into a row, come back, apply a filter, refresh, share a link, open a second tab. Every one of those actions is a chance to throw away their position, and doing so is the fastest way to make a product feel hostile. Encode the meaningful state — page or scroll offset, page size, active filters, sort order — in the URL so it can be restored, shared, and reproduced. Restore scroll position when a user navigates back from a detail view instead of resetting to the top. Keep the list stable enough that "the row I was looking at" is still findable after a round trip. This is unglamorous plumbing, but it is exactly the plumbing that decides whether someone can get real work done in your list or quietly gives up on it.
Loading, perceived speed, and large datasets
How a list loads shapes how fast the whole product feels, often more than the raw query time. When a page or batch is loading, hold the layout with skeleton placeholders that match the shape of the incoming rows rather than collapsing to a spinner and then jarringly reflowing — the list should feel like it is filling in, not rebuilding. Prefetch the next page when you can predict the user is heading there, so a "next" click feels instant. For very large or infinite datasets, virtualize the rendered rows so the browser only paints what is on screen, keeping scrolling smooth no matter how much data sits behind it. Avoid layout shift as new content arrives — reserve space and append below the fold, never shove the row the user is reading. Perceived performance is a design responsibility, not just an engineering one: the same data can feel snappy or sluggish depending entirely on how its arrival is choreographed.
Give lists honest empty and end states
A list has to say something useful when it has nothing more to show. The initial empty state — no data yet, or no results for the current filter — is a chance to orient and guide rather than present a blank void, and it should distinguish "you have not created anything" from "your filter matched nothing" because the right next action differs. The end state matters just as much: when a paginated or infinite list reaches its final item, say so plainly ("End of results", "No more activity") instead of leaving a spinner that promises data that will never come. These moments are easy to skip and disproportionately felt, because they are exactly when a user is unsure whether the product is broken or simply done.
How paging interacts with filtering, sorting, and bulk actions
Pagination never lives alone — it sits on top of filtering, sorting, and often bulk selection, and the interactions between them are where subtle bugs and confusion breed. When a user changes a filter or sort, reset to the first page, because "page 7 of the old result set" is meaningless against a new one; keep those filter and sort choices in the URL alongside the page so the whole view is reproducible. The thorniest interaction is bulk selection across pages: a "select all" checkbox that only selects the visible page while offering an action that sounds global is a genuine trap, so distinguish clearly between "select all 25 on this page" and "select all 1,182 matching" and make which one is active unmistakable before a destructive bulk action fires. Getting these seams right is what makes a data table feel like one coherent tool instead of three features that happen to share a screen.
The details that separate a trusted list from a frustrating one
As with most SaaS patterns, the mechanism is the easy part; the trust lives in the behaviors around it. These are the details mature products get right.
- The pattern chosen for the task — pagination for deliberate retrieval, infinite scroll for open-ended feeds, load-more when you want the flow without the side effects.
- Pagination controls that show position and total ("Showing 51–75 of 1,182") and let users jump to a page, not just step one at a time.
- Page, page size, sort, and filters encoded in the URL so the view is bookmarkable, shareable, and survives refresh and the back button.
- Scroll position and loaded state restored when returning from a detail view, so users never lose their place.
- Skeleton placeholders that match the incoming rows and reserved space that prevents layout shift as content loads.
- Virtualized rendering and prefetching for large sets, so scrolling and page changes feel instant regardless of data size.
- Honest empty and end states that distinguish "nothing yet" from "no matches" and clearly signal when a list is exhausted.
- A reset to page one on filter or sort change, and an unmistakable distinction between selecting the visible page and the whole result set.
- Footer and summary content kept out of any infinitely-growing column so it never becomes unreachable.
Common pagination and infinite-scroll mistakes
- Infinite scroll bolted onto a data table people need to navigate and return to, making deep-linking, place-keeping, and the footer impossible.
- Next/previous-only pagination with no page numbers, no jump, and no sense of how large the set is.
- Losing scroll position and loaded batches on back-navigation, forcing users to scroll from the top again.
- Page and filter state kept out of the URL, so a refresh or a shared link drops the user back to page one.
- A spinner-only loading state that reflows the layout when data arrives, instead of skeletons that hold the shape.
- An eternal spinner at the bottom of a finished list, with no clear end state.
- A "select all" that silently covers only the visible page while the bulk action implies the whole result set.
- Not resetting to the first page when the filter or sort changes, stranding users on a page that no longer exists.
Frequently asked questions
When should a SaaS use pagination versus infinite scroll?
Choose based on the user’s goal. Use classic pagination for data people navigate deliberately — tables, admin lists, search results, anything where someone might need to find a specific record, jump to a page, know the total size, or return to the same spot later. Use infinite scroll only for open-ended, discovery-style feeds where the point is continuous consumption and there is no meaningful position to hold, like an activity stream or notifications. When you want the effortless single-column flow of infinite scroll but need to avoid its downsides — unreachable footers, lost place, broken deep-links — a load-more button is often the best of both, keeping the flow while handing control back to the user.
Why is infinite scroll bad for data tables and productivity tools?
Because those tools require exactly the things infinite scroll takes away. It makes any footer or summary below the list unreachable, since content keeps loading before the user can get there. It removes any sense of scale or position, so users cannot tell how far through a set they are or how much remains. Most damaging, it loses your place on back-navigation — click into a row, hit back, and you land at the top of a freshly loaded list — and it breaks bookmarking and sharing because there is no stable "page" to link to. For lists people need to navigate precisely and return to, pagination preserves position, scale, and shareable state that infinite scroll destroys.
What makes pagination controls actually usable?
Go beyond blind next and previous. Show numbered pages plus a way to jump to the first, last, or an arbitrary page for large sets, so users are not clicking "next" dozens of times. Show position and total — "Page 3 of 47" or "Showing 51–75 of 1,182" — so the list is something a person can reason about. Let users pick page size when the task calls for it, and keep page, size, sort, and filters in the URL so the view is bookmarkable and survives refresh and the back button. Finally, keep the controls reachable without a marathon scroll, using a sticky or top-and-bottom placement for long tables.
How do you keep a list fast with very large datasets?
Treat perceived performance as a design job, not just a query-speed problem. Hold the layout with skeleton placeholders shaped like the incoming rows so the list feels like it is filling in rather than rebuilding, and reserve space so new content never shifts what the user is reading. Prefetch the next page when the user’s intent is predictable so navigation feels instant. Virtualize the rendered rows so the browser only paints what is on screen, keeping scroll smooth regardless of how many records sit behind it. Together these make a list of a hundred thousand rows feel as responsive as a list of ten.
Study real SaaS pagination and infinite-scroll patterns in the SaaSUI library
Every pattern above is easier to apply when you can see how real products solved it. Browse real tables, feeds, search results, and list views from shipped SaaS applications in the SaaSUI.Design library — real screenshots, not mockups — to study how mature products choose between pagination, infinite scroll, and load-more, surface position and totals, preserve place across navigation, and keep large lists feeling fast.

Interested in sponsoring SaaSUI.Design? Learn about sponsorship options →











