# Pagination
**Category**: react
**URL**: https://www.heroui.com/docs/react/components/pagination
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/pagination.mdx
> Page navigation with composable page links, previous/next buttons, and ellipsis indicators
***
## Import
```tsx
import { Pagination } from '@heroui/react';
```
### Usage
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationBasic() {
const [page, setPage] = useState(1);
const totalPages = 3;
return (
setPage((p) => p - 1)}>
Previous
{Array.from({length: totalPages}, (_, i) => i + 1).map((p) => (
setPage(p)}>
{p}
))}
setPage((p) => p + 1)}>
Next
);
}
```
### Anatomy
Import the Pagination component and access all parts using dot notation.
```tsx
import { Pagination } from '@heroui/react';
export default () => (
Showing 1-10 of 100 results
Previous
1
10
Next
);
```
### Sizes
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
function SizePagination({size}: {size: "sm" | "md" | "lg"}) {
const [page, setPage] = useState(1);
const totalPages = 3;
return (
{size}
setPage((p) => p - 1)}>
Previous
{Array.from({length: totalPages}, (_, i) => i + 1).map((p) => (
setPage(p)}>
{p}
))}
setPage((p) => p + 1)}>
Next
);
}
export function PaginationSizes() {
return (
{(["sm", "md", "lg"] as const).map((size) => (
))}
);
}
```
### With Ellipsis
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationWithEllipsis() {
const [page, setPage] = useState(1);
const totalPages = 12;
const getPageNumbers = () => {
const pages: (number | "ellipsis")[] = [];
pages.push(1);
if (page > 3) {
pages.push("ellipsis");
}
const start = Math.max(2, page - 1);
const end = Math.min(totalPages - 1, page + 1);
for (let i = start; i <= end; i++) {
pages.push(i);
}
if (page < totalPages - 2) {
pages.push("ellipsis");
}
pages.push(totalPages);
return pages;
};
return (
setPage((p) => p - 1)}>
Previous
{getPageNumbers().map((p, i) =>
p === "ellipsis" ? (
) : (
setPage(p)}>
{p}
),
)}
setPage((p) => p + 1)}>
Next
);
}
```
### Simple (Previous / Next)
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationSimplePrevNext() {
const [page, setPage] = useState(1);
const totalPages = 10;
const itemsPerPage = 5;
const totalItems = 50;
const startItem = (page - 1) * itemsPerPage + 1;
const endItem = Math.min(page * itemsPerPage, totalItems);
return (
{startItem} to {endItem} of {totalItems} invoices
setPage((p) => p - 1)}>
Prev
setPage((p) => p + 1)}>
Next
);
}
```
### With Summary
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationWithSummary() {
const [page, setPage] = useState(1);
const totalPages = 12;
const itemsPerPage = 10;
const totalItems = 120;
const getPageNumbers = () => {
const pages: (number | "ellipsis")[] = [];
pages.push(1);
if (page > 3) {
pages.push("ellipsis");
}
const start = Math.max(2, page - 1);
const end = Math.min(totalPages - 1, page + 1);
for (let i = start; i <= end; i++) {
pages.push(i);
}
if (page < totalPages - 2) {
pages.push("ellipsis");
}
pages.push(totalPages);
return pages;
};
const startItem = (page - 1) * itemsPerPage + 1;
const endItem = Math.min(page * itemsPerPage, totalItems);
return (
Showing {startItem}-{endItem} of {totalItems} results
setPage((p) => p - 1)}>
Previous
{getPageNumbers().map((p, i) =>
p === "ellipsis" ? (
) : (
setPage(p)}>
{p}
),
)}
setPage((p) => p + 1)}>
Next
);
}
```
### Custom Icons
You can replace the default chevron icons by passing custom children to `PreviousIcon` and `NextIcon`.
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {Icon} from "@iconify/react";
import {useState} from "react";
export function PaginationCustomIcons() {
const [page, setPage] = useState(1);
const totalPages = 3;
return (
setPage((p) => p - 1)}>
Back
{Array.from({length: totalPages}, (_, i) => i + 1).map((p) => (
setPage(p)}>
{p}
))}
setPage((p) => p + 1)}>
Forward
);
}
```
### Controlled
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationControlled() {
const [page, setPage] = useState(1);
const totalPages = 12;
const itemsPerPage = 10;
const totalItems = 120;
const getPageNumbers = () => {
const pages: (number | "ellipsis")[] = [];
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
pages.push(1);
if (page > 3) {
pages.push("ellipsis");
}
const start = Math.max(2, page - 1);
const end = Math.min(totalPages - 1, page + 1);
for (let i = start; i <= end; i++) {
pages.push(i);
}
if (page < totalPages - 2) {
pages.push("ellipsis");
}
pages.push(totalPages);
}
return pages;
};
const startItem = (page - 1) * itemsPerPage + 1;
const endItem = Math.min(page * itemsPerPage, totalItems);
return (
Showing {startItem}-{endItem} of {totalItems} results
setPage((p) => p - 1)}>
Previous
{getPageNumbers().map((p, i) =>
p === "ellipsis" ? (
) : (
setPage(p)}>
{p}
),
)}
setPage((p) => p + 1)}>
Next
);
}
```
### Disabled
```tsx
"use client";
import {Pagination} from "@heroui/react";
import {useState} from "react";
export function PaginationDisabled() {
const [page, setPage] = useState(1);
const totalPages = 3;
return (
setPage((p) => p - 1)}>
Previous
{Array.from({length: totalPages}, (_, i) => i + 1).map((p) => (
setPage(p)}>
{p}
))}
setPage((p) => p + 1)}>
Next
);
}
```
## Related Components
- **Button**: Allows a user to perform an action
- **Link**: Styled anchor links
## Styling
### Passing Tailwind CSS classes
You can customize individual Pagination parts:
```tsx
import { Pagination } from '@heroui/react';
function CustomPagination() {
return (
1
);
}
```
### Customizing the component classes
To customize the Pagination component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.pagination {
@apply gap-8;
}
.pagination__link {
@apply rounded-md;
}
.pagination__summary {
@apply text-xs font-semibold;
}
}
```
HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Pagination component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/pagination.css)):
#### Base & Layout Classes
- `.pagination` - Root navigation container with flex layout
- `.pagination__summary` - Left-side info text container
- `.pagination__content` - Container for pagination items
- `.pagination__item` - Individual item wrapper
- `.pagination__link` - Page number button (ghost button style)
- `.pagination__link--nav` - Navigation button modifier (Previous/Next)
- `.pagination__ellipsis` - Ellipsis indicator
#### Size Classes
- `.pagination--sm` - Small size variant
- `.pagination--md` - Medium size variant (default)
- `.pagination--lg` - Large size variant
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Active page**: `[data-active="true"]` or `[aria-current="page"]`
- **Hover**: `:hover` or `[data-hovered="true"]`
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
- **Disabled**: `:disabled` or `[aria-disabled="true"]`
- **Pressed**: `:active` or `[data-pressed="true"]`
## API Reference
### Pagination Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the pagination items |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Pagination parts (Summary, Content) |
### Pagination.Summary Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Summary content (e.g., "Showing 1-10 of 120") |
### Pagination.Content Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Pagination items |
### Pagination.Item Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Item content (Link, Previous, Next, or Ellipsis) |
### Pagination.Link Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `isActive` | `boolean` | `false` | Whether this is the current page |
| `isDisabled` | `boolean` | `false` | Whether the link is disabled |
| `onPress` | `(e: PressEvent) => void` | - | Press handler (from React Aria) |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Page number content |
### Pagination.Previous / Pagination.Next Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `isDisabled` | `boolean` | `false` | Whether the button is disabled |
| `onPress` | `(e: PressEvent) => void` | - | Press handler (from React Aria) |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Button content (compose with PreviousIcon/NextIcon) |
### Pagination.PreviousIcon / Pagination.NextIcon Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | Default chevron SVG | Custom icon to replace the default chevron |
### Pagination.Ellipsis Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
## Accessibility
The Pagination component is built on [React Aria's Button](https://react-spectrum.adobe.com/react-aria/Button.html) primitive for all interactive elements, providing:
- Semantic `