Paginator

A paginator component allows users to navigate through multiple pages of content by selecting page numbers or using previous/next controls.

UsageCodeAccessibility
<sl-paginator-status></sl-paginator-status>
<sl-paginator></sl-paginator>
<sl-paginator-page-size page-size="10" page-sizes="[5,10,15]"></sl-paginator-page-size>

<script>
  // This is an example with manual management of the pagination state

  const paginatorStatus = document.querySelector('sl-paginator-status');
  const paginator = document.querySelector('sl-paginator');
  const paginatorPageSize = document.querySelector('sl-paginator-page-size');

  const students = Array.from({ length: 120 }).map((_, index) => `Student ${index + 1}`);

  const update = ({ page, pageSize }) => {
    if (typeof pageSize === 'number' && pageSize !== paginator.pageSize) {
      page = 0;
    } else {
      page ??= paginator.page;
    }

    pageSize ??= paginator.pageSize;

    paginator.page = paginatorPageSize.page = page;
    paginator.pageSize = paginatorPageSize.pageSize = pageSize;
  };

  const onPageChange = ({ detail: page }) => update({ page });

  const onPageSizeChange = ({ detail: pageSize }) => update({ pageSize });

  paginator?.addEventListener('sl-page-change', onPageChange);

  paginatorPageSize?.addEventListener('sl-page-size-change', onPageSizeChange);

  paginator.totalItems = students.length;
  paginatorStatus.totalItems = students.length;

  paginatorStatus.itemLabel = 'students';
  paginatorPageSize.itemLabel = 'Students';
</script>

When to use

Large Datasets

When there is too much data to display within a single page or component view, and you want to break it into manageable chunks so users can scan, compare, and keep their place more easily. Also when loading all available data at once would be slow, heavy or resource-intensive, and you need to keep performance predictable.

Precise Navigation

When users need explicit control over where they are in a list, for example, jumping to a specific page, returning to a remembered page number, or sharing a URL that always opens the same subset of results.

When not to use

Linear Journeys Flows

For multi-step processes such as forms, wizards, or checkout flows where the user should move forward or backward step by step. In these cases, use buttons or a progress indicator instead of paginator.

Short, Small, or Simple Content

When the content fits comfortably on a single page without performance issues, or when the dataset is small gives a simpler, more natural experience.

Anatomy

Page Size

Control that lets users choose how many items are shown per page. Changing this value recalculates the total number of pages.

ItemNameDescriptionOptional
1LabelText that describes the page size control (e.g. “Items per page”).yes
2SelectDropdown used to choose how many items are displayed per page.yes

Paginator

The main navigation for moving across pages.

ItemNameDescriptionOptional
1Prev/Next buttonsMove one page backward or forward. Previous is disabled on the first page, and Next is disabled on the last page.yes
2Page ButtonA numbered button that takes the user to a specific page.yes
3Selected pageThe current page, visually highlighted.yes
4Overflow ButtonA menu button that exposes hidden pages when there are more pages than can be displayed at once.yes

Status

Text that communicates where the user is in the full result set, typically:

ItemNameDescriptionOptional
1Range ItemsText element that displays the current range, the start and end of it.yes
2Total ItemsText element that displays the total.yes
3Items LabelText that describes the items in the range (e.g. “items”, “results”).yes

Widths

Control how many page buttons are visible at once before pages are moved into the overflow menu.

  • LG: Shows up to 13 page items in a single row.
  • MD: Shows up to 11 page items.
  • SM: Shows up to 9 page items.
  • XS: When the available space is very limited, page buttons are replaced by a single select field so users can pick a page from a dropdown.

Use wider versions when the Paginator is a primary control, for example, at the bottom of a data table and narrower versions when space is constrained or the pagination is secondary.

Emphasis

The Paginator supports two emphasis levels:

  • Subtle: Low-contrast styling that keeps pagination in the background while still discoverable. Use when pagination is supportive, not the main focus of the page.
  • Bold: Higher visual weight for cases where pagination is a primary navigation element or is critical to the user’s workflow.

Choose the emphasis that matches the visual hierarchy of surrounding content.

Sizes

The Paginator offers three control sizes:

  • Large: For dense layouts, large data tables or touch-first experiences where targets need to be easier to hit.
  • Medium: The default size for most use cases and general content pages.
  • Small: For compact layouts, side panels, or areas where vertical space is limited.

Ideally, match the Paginator size to the height of related controls, for example, table rows or filter inputs.

Figma Options

With these options, you can tweak the appearance of the paginator in Figma. They are available in the Design Panel so you can compose the paginator to exactly fit the user experience need for the use case you are working on.

Paginator

ItemOptionsDescription
Sizelg, md, smSets the paginator control size.
Widthlg, md, sm, xsDefines how many page buttons are visible before overflow.
Emphasissubtle, boldSets the visual impact style.
Arrow StartbooleanControls visibility of the previous-page arrow.
Overflow StartbooleanControls visibility of the leading overflow.
Overflow EndbooleanControls visibility of the trailing overflow.
Arrow EndbooleanControls visibility of the next-page arrow.

Paginator Status

ItemOptionsDescription
Item labeltextText label used for items (e.g. “items”, students).
Total RangenumberTotal number of items in the dataset.
High RangenumberLast item index displayed on the current page.
Low RangenumberFirst item index displayed on the current page.

Paginator Size

ItemOptionsDescription
Item labeltextChange the "Items" label for the page size control.

Behaviours

Keyboard navigation

Users can move through the Paginator with the keyboard using Tab and Shift+Tab to follow a logical focus order across controls, and use Enter or Space to activate Previous and Next, select a page, or open and confirm options in overflow menus, while arrow keys help navigate within any the overflow dropdown.

Overflow pages

When there are more pages than can be shown at once, hidden pages are moved into an overflow menu represented by an ellipsis, which adapts depending on the current page (start or end of the range) while keeping the overall layout stable and avoiding any width changes.

Responsive behaviour

On larger viewports, the Paginator can show more page buttons alongside Previous and Next, while on smaller or constrained layouts it reduces the number of visible pages and, at the narrowest widths, can replace numbered buttons with a page select field to keep pagination usable and readable on mobile.

  • Text Field: If you want a free-form text input.
  • Select: Selecting from predefined numeric options.
<sl-paginator-status id="status"></sl-paginator-status>
<sl-paginator id="paginator"></sl-paginator>
<sl-paginator-page-size id="page-size" page-sizes="[5,10,15,20]"></sl-paginator-page-size>

<script>
// This is an example with DataSource managing the pagination state

import { ArrayListDataSource } from '@sl-design-system/data-source';

const paginatorStatus = document.querySelector("#status");
const paginator = document.querySelector("#paginator");
const pageSize = document.querySelector("#page-size");

const exams = Array.from({ length: 60 }).map((_, index) => `Exam ${index + 1}`);

const ds = new ArrayListDataSource(exams, {
  pagination: true,
  page: 1,
  pageSize: 10
});

paginatorStatus.dataSource = ds;
paginator.dataSource = ds;
pageSize.dataSource = ds;
</script>

Using data source with paginator

A data source is an interface that manages data fetching, state, and pagination logic. It allows you to connect paginator components to your data in a consistent way, whether that data comes from an API, an in memory array, or any other source.

Setting up a data source

To use a data source with the paginator components, follow these steps:

  1. Create a data source instance - Use FetchListDataSource for API based data or ArrayListDataSource for in memory arrays. You can also implement your own data source by extending the ListDataSource class and implementing the required methods.
  2. Configure pagination settings - Set pageSize and enable pagination.
  3. Implement data fetching - Define the fetchPage method to retrieve data for each page (for API based data).
  4. Connect to components - Assign the same data source instance to sl-paginator, sl-paginator-status, and sl-paginator-page-size.

Example

const ds = new FetchListDataSource({
  pageSize: 10,
  pagination: true,
  fetchPage: async ({ page, pageSize }) => {
    const response = await fetch(
      `https://api.example.com/data?skip=${page * pageSize}&limit=${pageSize}`
    );
    
    if (response.ok) {
      const { items, total } = await response.json();
      return { items, totalItems: total };
    } else {
      throw new FetchListDataSourceError('Failed to fetch data', response);
    }
  }
});

// Connect the data source to all paginator components
paginatorStatus.dataSource = ds;
paginator.dataSource = ds;
pageSize.dataSource = ds;

Once connected, the paginator components will automatically:

  • Display the correct page information
  • Fetch new data when users navigate between pages
  • Update when the page size changes
  • Show the total number of items and current range

Paginator page size API

Paginator page size component provides properties to configure available page size options and current selection.

Properties

NameAttributeTypeDefaultDescription
dataSource-ListDataSource<T> | undefinedBy setting a dataSource, the paginator will listen for changes on the data source and control the data source when the user selects a new page in the component. This can be very useful when the paginator is used in combination with a data source-driven component, such as <sl-grid>.
itemLabel-string | undefinedThe label to display for the 'items' per page selector. If not set, defaults to "Items". You can use this to set a custom label, such as "Students" or "Books" or something else. Please remember to provide a translation for the label in your application.
pageSizepage-sizenumberItems per page.
pageSizespage-sizesnumber[] | undefinedAvailable page sizes.

Events

NameEvent typeDescription
sl-page-size-changeSlChangeEvent<number>Emits when the page size has been selected/changed.

Paginator API

The paginator component offers settings for various scenarios.

Properties

NameAttributeTypeDefaultDescription
dataSource-ListDataSource<T> | undefinedBy setting a dataSource, the paginator will listen for changes on the data source and control the data source when the user selects a new page in the component. This can be very useful when the paginator is used in combination with a data source-driven component, such as <sl-grid>.
emphasisemphasis'subtle' | 'bold' | undefined'subtle'The emphasis style.
pagepagenumber0Current page.
pageSizepage-sizeLIST_DATA_SOURCE_DEFAULT_PAGE_SIZEItems per page. Default to the first item of pageSizes.
sizesize'sm' | 'md' | 'lg' | undefined'md'The size of the paginator which determines the size of the elements in it.
totalItemstotal-itemsnumber1Total number of items.
widthwidth'xs' | 'sm' | 'md' | 'lg' | undefinedThe width of the paginator. This is used to determine how many pages are visible at once. For xs a select component will be used to select the page. For all other widths, buttons will be used.

Events

NameEvent typeDescription
sl-page-changeSlChangeEvent<number>Emits when the page has been changed.

Paginator status API

Paginator status component displays pagination information using page, pageSize, and totalItems properties.

Properties

NameAttributeTypeDefaultDescription
dataSource-ListDataSource<T> | undefinedBy setting a dataSource, the component will listen for changes on the data source and control the data source when the user selects a new page size in the component.
itemLabel-string | undefinedThe label to display for the 'items'. If not set, defaults to "Items". You can use this to set a custom label, such as "students" or "books" or something else. Please remember to provide a translation for the label in your application.
pagepagenumber0Current page.
pageSizepage-sizeLIST_DATA_SOURCE_DEFAULT_PAGE_SIZEItems per page.
totalItemstotal-itemsnumber1Total number of items.

Keyboard interactions

The paginator provides full keyboard navigation to move between the pages of a list:

CommandDescription
TabMoves focus through the paginator controls: previous button, page buttons, next button, and page select dropdown (on smaller widths).
Shift + TabMoves focus backward through the paginator controls.
Enter or SpaceActivates the focused button to navigate to the selected page, or opens the page select dropdown.
Arrow keysWhen the page select dropdown is focused, use up/down arrows to navigate between page options.

Announcements

The paginator provides screen reader announcements for important state changes:

  • Page changes: When navigating between pages using previous/next buttons or selecting a page directly, the new page number and total pages are announced.
  • Page size changes: When changing the number of items per page, the new page size is announced to inform users of the updated display.
  • Status updates: When the page, page size, or total items change, the current page range and total item count are immediately announced to screen readers to provide context about the displayed content.

These announcements help users understand pagination changes without needing to navigate back to check the current state.

WAI-ARIA

In the component itself we use multiple aria-attributes to assure the component works well with a range of assistive technologies. For some attributes however it is not possible for the Design System to add a meaningful value, because it relies on the context or way a component is used.

Attributes that we recommend you add in certain scenarios are mentioned below.

Paginator

AttributeValueDescription
aria-labelstringLabels the navigation region. Defaults to "Pagination" if not provided.
Interactive example