Nº 330 of 520
Pagination
Pages of a 48-row list, ten at a time. Page 2 starts current. Previous and Next disable at the ends. The count line shows the range.
Preview
Use it
Free to use · credit appreciated1 Once, in your project
npx skills add SusanAcharya/Design-Lounge 2 Then ask
Using the Design Lounge skill, build "Pagination" (piece pagination) in my stack. Match its brief; restyle it onto my product's theme.
No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.
<!-- Design Lounge Nº 330 · "Pagination" · designlounge.vercel.app -->
# Pagination
> **Build brief for a coding agent.** Rebuild this piece in the reader's stack. If they haven't said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don't "improve" them. When a kit is locked, the current page uses `--primary-soft` and the control height follows the family. Do not draw a second radius on the page buttons.
## What it is
The control under a long list. Forty-eight rows, ten per page, five pages. The demo starts on page 2 so Previous is alive and the current page is not the first. The count reads "11–20 of 48". The current page sits on the soft green. Previous and Next are words, not icons alone. This list does not render the rows. `dense-data-table` and `people-role-list` are the rows. People-role-list is short and has no pages. Add this piece when the list is longer than one screen.
## Reference behaviour
1. Page 2 has `aria-current="page"`. The count is 11–20 of 48. Previous and Next are enabled.
2. Clicking a number goes to that page. The count becomes the matching slice: page 1 is 1–10, page 5 is 41–48.
3. Next adds one page. Previous subtracts one.
4. On page 1, Previous is disabled. On page 5, Next is disabled.
5. There is no animation. The count changes in one frame.
6. Focus ring is 2px `--focus`, offset 2px.
## Structure
```
padding 48px 64px
11–20 of 48 14px
[ Previous ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ Next ]
each control min 40px, height 40
```
- `nav` with `aria-label="Pages"`.
- Number buttons carry `data-page`. The current one carries `aria-current="page"`.
- Previous and Next are buttons, not links, in this demo.
## Tokens
```css
:root {
--bg: #f6f4ef;
--surface: #ffffff;
--ink: #161513;
--ink-2: #5a554c;
… 123 more lines. Copy or download for the full brief. Loading the source…Brief
163 linesBuild brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them. When a kit is locked, the current page uses
--primary-softand the control height follows the family. Do not draw a second radius on the page buttons.
What it is
The control under a long list. Forty-eight rows, ten per page, five pages. The demo starts on page 2 so Previous is alive and the current page is not the first. The count reads “11–20 of 48”. The current page sits on the soft green. Previous and Next are words, not icons alone. This list does not render the rows. dense-data-table and people-role-list are the rows. People-role-list is short and has no pages. Add this piece when the list is longer than one screen.
Reference behaviour
- Page 2 has
aria-current="page". The count is 11–20 of 48. Previous and Next are enabled. - Clicking a number goes to that page. The count becomes the matching slice: page 1 is 1–10, page 5 is 41–48.
- Next adds one page. Previous subtracts one.
- On page 1, Previous is disabled. On page 5, Next is disabled.
- There is no animation. The count changes in one frame.
- Focus ring is 2px
--focus, offset 2px.
Structure
padding 48px 64px
11–20 of 48 14px
[ Previous ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ Next ]
each control min 40px, height 40
navwitharia-label="Pages".- Number buttons carry
data-page. The current one carriesaria-current="page". - Previous and Next are buttons, not links, in this demo.
Tokens
:root {
--bg: #f6f4ef;
--surface: #ffffff;
--ink: #161513;
--ink-2: #5a554c;
--primary-soft: #e7f2ec;
--focus: #1f4d3a;
--sans: "IBM Plex Sans", system-ui, sans-serif;
}
Radius is 2px in this yard demo. The family replaces it. The current page is --primary-soft, the same selected treatment as a row. It is not a solid primary button.
Typography
| Role | Family | Size | Weight | Colour |
|---|---|---|---|---|
| Count | sans | 14px | 400 | --ink-2 |
| Page | sans | 13px | 500 | --ink |
The count uses tabular numbers and an en dash between the start and the end. Letter-spacing on the buttons is 0.
Motion
None. Reduced motion has nothing to remove. Do not slide the row of numbers.
| Thing | Trigger | What changes |
|---|---|---|
| Number | click | current page, count line |
| Previous, Next | click | one page toward the end or the start |
| Ends | page 1 or 5 | the matching button disabled |
States
- Page resting: min-width 40px, height 40px, padding 0 12px, transparent, radius 2px.
- Page hover: background
--surface. - Page current: background
--primary-soft. No border. - Previous and Next: same height, horizontal padding 12px, words visible.
- Disabled: opacity 0.4,
disabled, not clickable. - Focus-visible: 2px outline, offset 2px.
- Do not put the current page in
--primarywith light text. Selected is the soft fill.
Accessibility
- The nav label is Pages.
aria-current="page"marks the current number. Remove it from the others.- Previous and Next have visible names. Do not use a chevron as the only name.
- Disabled buttons leave the tab order.
- Hit target: 40px. On a phone, at least 44px.
- Contrast:
#161513on#e7f2ecand on the paper clears 4.5. - The count is text, not only a visual highlight, so the range is available without seeing which square is green.
Responsive rules
- At 1280 the row is one line, padding 48px 64px.
- Below 640, keep Previous, the current page, and Next. Hide the far numbers if they do not fit, but do not hide the count. This demo’s five pages fit at 360 if the gap stays 4px. If you drop numbers, keep the current one.
- Do not switch to an infinite scroll without saying so. This piece is pages.
Acceptance checklist
- The first frame is page 2 and the count is 11–20 of 48.
- Page 2 has
aria-current="page"and background#e7f2ec. - Clicking 5 sets the count to 41–48 and disables Next.
- Clicking 1 sets the count to 1–10 and disables Previous.
- Next and Previous move one page.
- There are five page numbers, for 48 rows at 10 per page.
- Controls are 40px tall, radius 2px.
- The current page is not a solid primary.
- Focus ring is 2px, offset 2px.
- There is no animation.
Implementation notes
Derive the count from the page. Do not store five strings.
const start = (page - 1) * 10 + 1;
const end = Math.min(page * 10, total);
count.textContent = start + '–' + end + ' of ' + total;
The dash is an en dash.
Common mistakes:
- A current page painted as a solid primary button, so it looks like the one commit action.
- Icon-only Previous and Next.
- Page 1 of 1 on a short list.
people-role-listhas no pagination. Do not add it. - Ellipses that hide every page including the current one.
- Loading the next page in a toast.
- A radius that ignores the family.
- Infinite scroll with no count, on a list the person must audit.
- Mixing this with a filter and forgetting to reset to page 1 when the filter changes.
filter-toolbaris the filter. When both are on a screen, a new filter returns to page 1.
Where it sits in a product:
- Place it under the list, or above it with the count. This demo is the control alone.
- Ten rows is this demo’s page size. A dense table may use twenty. Say the number in the count.
- The last page may be short. Page 5 is 41–48, not 41–50.
- Selected is
--primary-soft. - The family wins the radius and the height.
- When a theme is locked, the soft fill is that theme’s
--primary-soft. - Do not paginate a conversation.
chat-threadgrows by the messages you have. - Do not paginate three radios.
- The count is the proof. A highlight without a range is not enough.
- Keep the credit line on the token block.
Rebuild order:
- Set the paper and IBM Plex Sans.
- Place the count and the nav.
- Start on page 2.
- Wire numbers, Previous, and Next.
- Disable the ends.
- Check page 5 ends at 48.
- Map the current fill onto
--primary-softwhen a kit is on.
Copy you keep:
- Previous. Next.
- Pages 1 through 5.
- The count pattern: start–end of 48.
- Ten rows a page. Forty-eight rows.
Details
- Palette
- Type
- IBM Plex Sans
- Motion
- Static
- Build
- Quick build
- Tags
On the shelves