#Algorithms#Components

Pagination With Ellipsis

A pagination control that always shows the first, last and current pages, collapsing every gap into a single ellipsis.

By Pratik RaiMedium

Build <Pagination currPage totalPage onPageClick />. Page 1, the last page, the current page and its immediate neighbours are always visible; anywhere numbers are missing between two visible ones, a single stands in.

This looks like a layout problem and is really an off-by-one problem. Reasoning about it as ranges — "if the current page is near the start show these, near the end show those, otherwise…" — produces three branches and a bug at the boundary between them, every time.

Splitting it in two removes the branches. First derive the visible set: page 1, the last page, and the current page with its neighbours, dropped into a Set and clamped to range. Deduplication and clamping then happen once, declaratively, and currPage 1 producing 1 2 … 10 needs no special handling. Then insert the gaps by walking the sorted list and comparing consecutive values: a difference greater than one means numbers are missing.

The cases an interviewer will actually try are the small ones. With one, two or three total pages the visible set already covers everything, so no ellipsis appears — not because you handled it, but because there is no gap to find. Deriving from a set is what makes those free.

The markup matters too: numbers are buttons because they are actions, the ellipsis is inert and aria-hidden, and aria-current="page" is what conveys the current page beyond colour.

Goal: Render the visible page numbers with gaps collapsed, correct at every boundary.

Source

Frequently asked questions

How do you decide which page numbers to show?
Collect the always-visible ones — first, last, current and its neighbours — into a `Set`, drop anything out of range, and sort. Deduplication and clamping then happen once, before any layout logic.
How do you know where to put the ellipsis?
Walk the sorted list of visible pages and compare each with the previous one. A difference greater than one means numbers are missing there, so insert a single ellipsis.
Why do range-based implementations have boundary bugs?
Because they branch on where the current page sits — near the start, near the end, in the middle — and the branches disagree at the point they meet. Deriving a set removes the branches entirely.
What happens with only two or three pages?
The visible set already covers every page, so no gap exists and no ellipsis is inserted. That falls out of the approach rather than needing a special case, which is why small totals are the first thing an interviewer tries.

Related Challenges

Continue learning with these related challenges

View All
React

Nested Tabs From a Flat Array

Given a flat array of items with parentId, render them as nested tabs at arbitrary depth.

React · JavaScriptPratik Rai ·

React

Accessible Dropdown

A select built from scratch — keyboard navigation, focus management, outside-click and the full ARIA listbox contract.

React · JavaScriptPratik Rai ·

React

Seat Booking Grid

A cinema seat picker: rows at different prices, sold seats, a selection limit and a running total.

React · JavaScriptPratik Rai ·