Skip to main content
View Zag.js on Github
Join the Discord server


Pagination is an interface that allows navigating between pages that contain split information, instead of being shown on a single page.



  • Full keyboard navigation.
  • Optimized for screen readers.


To use the pagination machine in your project, run the following command in your command line:

npm install @zag-js/pagination @zag-js/react # or yarn add @zag-js/pagination @zag-js/react

This command will install the framework agnostic pagination logic and the reactive utilities for your framework of choice.


To set up the pagination correctly, you'll need to understand its anatomy and how we name its parts.

Each part includes a data-part attribute to help identify them in the DOM.

On a high level, the pagination consists of:

  • Root: The root container for the pagination
  • Item: Each pagination item
  • Ellipsis: Ellipsis shown when some items are hidden
  • Previous Button: Used to go to previous page in pagination
  • Next Button: Used to go to next page in pagination


First, import the pagination package into your project

import * as pagination from "@zag-js/pagination"

The pagination package exports two key functions:

  • machine — The state machine logic for the pagination widget.
  • connect — The function that translates the machine's state to JSX attributes and event handlers.

You'll also need to provide a unique id to the useMachine hook. This is used to ensure that every part has a unique identifier.

import * as pagination from "@zag-js/pagination" import { useMachine, normalizeProps } from "@zag-js/react" import { data } from "./data" function Pagination() { const [state, send] = useMachine( pagination.machine({ id: "1", count: data.length }), ) const api = pagination.connect(state, send, normalizeProps) return ( <div> {api.totalPages > 1 && ( <nav {...api.rootProps}> <ul> <li> <a href="#previous" {...api.prevItemProps}> Previous <span className="visually-hidden">Page</span> </a> </li> {, i) => { if (page.type === "page") return ( <li key={page.value}> <a href={`#${page.value}`} {...api.getItemProps(page)}> {page.value} </a> </li> ) else return ( <li key={`ellipsis-${i}`}> <span {...api.getEllipsisProps({ index: i })}>&#8230;</span> </li> ) })} <li> <a href="#next" {...api.nextItemProps}> Next <span className="visually-hidden">Page</span> </a> </li> </ul> </nav> )} </div> ) }

Methods and Properties

The pagination's api exposes the following methods and properties:

  • page — The currently selected page.
  • totalPages — The total number of pages.
  • pages — An array of page properties used to render pagination items.
  • previousPage — The previous page.
  • nextPage — The next page.
  • pageRange — Index of the first and last item for current page, helpful for splicing data.
  • isFirstPage — Whether current page is first page.
  • isLastPage — Whether current page is last page.
  • setCount() — Set the number of data items.
  • setPageSize() — Set the number of items to display per page.
  • setPage() — Programmatically set the current page.
const api = connect(state, send) // You can slice the data, to get data for current page const currentPageData = data.slice(api.pageRange.start, api.pageRange.end) // => 1 api.isFirstPage() // => true api.setPage(3) // page => 3 api.previousPage // => 2 api.nextPage // => 4 api.pages /* [ { "type": "page", "value": 1, }, { "type": "page", "value": 2, }, { "type": "ellipsis", }, { "type": "page", "value": 3, }, { "type": "page", "value": 4, }, ] */ api.pageRange // => { start: 4, end: 13 }

Styling guide

Earlier, we mentioned that each pagination part has a data-part attribute added to them to select and style them in the DOM.

[data-part="root"] { /* styles for the pagination's root */ } [data-part="item"] { /* styles for the pagination's items */ } [data-part="ellipsis"] { /* styles for the pagination's ellipsis */ } [data-part="prev-item"] { /* styles for the pagination's previous item */ } [data-part="next-item"] { /* styles for the pagination's next item */ } /* We add a data-disabled attribute to the prev/next items when on the first/last page */ [data-part="prev-item"][data-disabled] { /* styles for the pagination's previous item when on first page */ } [data-part="next-item"][data-disabled] { /* styles for the pagination's next item when on first page */ }

Edit this page on GitHub

On this page