Liking cljdoc? Tell your friends :D

x-pagination

A stateless native Web Component that renders a numbered page control with prev/next navigation and ellipsis for large page ranges.


Tag name

<x-pagination page="1" total-pages="20"></x-pagination>

Observed Attributes

AttributeTypeDefaultNotes
pageinteger1Current page, 1-indexed. Clamped to [1, total-pages].
total-pagesinteger1Total page count. Values ≤ 0 treated as 1.
sibling-countinteger1Pages shown on each side of the current page.
boundary-countinteger1Pages always shown at the start and end of the range.
sizestring"md"Button size preset: sm | md | lg.
disabledbooleanfalseDisables all buttons and suppresses events.
labelstring"Pagination"aria-label value on the <nav> element.

Reflected Properties

PropertyTypeReflects attribute
pagenumberpage
disabledbooleandisabled
const el = document.querySelector('x-pagination');
el.page = 3;        // sets attribute page="3"
el.disabled = true; // sets attribute disabled=""

Events

EventDetailFires when
page-change{ page: number }A page button, prev, or next is clicked

The event bubbles and is composed (crosses shadow DOM boundary).

el.addEventListener('page-change', e => {
  console.log(e.detail.page); // e.g. 4
  el.setAttribute('page', String(e.detail.page));
});

The component does not update page itself — the consumer must reflect the new page back as an attribute or property.


Slots

SlotDefault contentNotes
prev"Prev"Content inside the Previous <button>
next"Next"Content inside the Next <button>
<x-pagination page="5" total-pages="10">
  <span slot="prev">← Back</span>
  <span slot="next">Forward →</span>
</x-pagination>

CSS Custom Properties

PropertyDefault (light)Notes
--x-pagination-gap0.25remGap between buttons
--x-pagination-button-size2remHeight and min-width of buttons
--x-pagination-button-radius0.375remBorder radius
--x-pagination-button-bgtransparentDefault button background
--x-pagination-button-colorrgba(0,0,0,0.75)Default button text colour
--x-pagination-button-border1px solid rgba(0,0,0,0.15)Default button border
--x-pagination-button-hover-bgrgba(0,0,0,0.06)Hover background
--x-pagination-button-hover-colorrgba(0,0,0,0.9)Hover text colour
--x-pagination-current-bgrgba(0,0,0,0.88)Current page button background
--x-pagination-current-color#fffCurrent page button text colour
--x-pagination-current-border1px solid transparentCurrent page button border
--x-pagination-disabled-opacity0.4Opacity for disabled buttons
--x-pagination-font-size0.875remFont size (overridden by size)
--x-pagination-ellipsis-colorrgba(0,0,0,0.45)Ellipsis symbol colour

Dark mode defaults are applied automatically via @media (prefers-color-scheme: dark).

Size presets adjust --x-pagination-button-size and --x-pagination-font-size:

  • sm: 1.75rem / 0.75rem
  • md: 2rem / 0.875rem (default)
  • lg: 2.5rem / 1rem

Custom theme example

x-pagination {
  --x-pagination-button-radius: 9999px;
  --x-pagination-current-bg: #7c3aed;
  --x-pagination-current-color: #fff;
  --x-pagination-button-hover-bg: rgba(124, 58, 237, 0.1);
  --x-pagination-button-hover-color: #7c3aed;
}

Shadow DOM Parts

PartElement
navThe <nav> wrapper
listThe <ol> element
itemAny <li> element
item-prevThe Previous <li>
item-nextThe Next <li>
item-pageA page number <li>
item-ellipsisAn ellipsis <li>
buttonAny <button> element
button-prevThe Previous <button>
button-nextThe Next <button>
button-pageA page number <button>
ellipsisThe ellipsis <span>
x-pagination::part(button-page) {
  font-weight: 700;
}

Page Range Algorithm

The visible page items are computed as the sorted union of three sets:

  1. Left boundary — pages 1..boundary-count
  2. Right boundary — pages (total-pages - boundary-count + 1)..total-pages
  3. Mid window — pages (page - sibling-count)..(page + sibling-count), clamped to [1, total-pages]

An ellipsis is inserted wherever consecutive visible page numbers have a gap greater than 1.


Accessibility

  • The <nav> element has aria-label (defaults to "Pagination"; customise via the label attribute).
  • The current page button has aria-current="page".
  • Ellipsis <span> elements have aria-hidden="true".
  • Prev/next buttons have descriptive aria-label attributes ("Previous page", "Next page").
  • All buttons are individually focusable via Tab; Enter/Space activates them.
  • @media (prefers-reduced-motion: reduce) disables transitions.

Usage Examples

Basic

<x-pagination page="1" total-pages="20"></x-pagination>

Controlled (update on change)

<x-pagination id="pg" page="1" total-pages="50"></x-pagination>
<script>
  document.getElementById('pg').addEventListener('page-change', e => {
    e.target.setAttribute('page', String(e.detail.page));
  });
</script>

Custom sibling and boundary counts

<!-- Show 2 pages on each side of current, 2 at each boundary -->
<x-pagination page="10" total-pages="50"
              sibling-count="2" boundary-count="2"></x-pagination>

Small size

<x-pagination page="3" total-pages="10" size="sm"></x-pagination>

Custom labels

<x-pagination page="3" total-pages="10" label="Article navigation">
  <span slot="prev">← Previous</span>
  <span slot="next">Next →</span>
</x-pagination>

ESM import

import { init } from '@vanelsas/baredom/x-pagination';
init();

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close