Skip to main content
Vuetify0 v1.0 is here
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Pagination

A headless component for creating page navigation with proper ARIA support.

Edit this page
Report a Bug
Open issues
View on GitHub
Copy Markdown

PreviewRenders elementIntermediateJul 19, 2026

Usage

The Pagination component provides a compound component pattern for building page navigation interfaces. It adjusts how many page buttons it shows to fit the available width, collapsing the overflow behind ellipses.

The two core props are size (total item count) and items-per-page (items per page, default 10). Together they determine the page count:

vue
<template>
  <!-- 200 items at 10 per page = 20 pages -->
  <Pagination.Root :size="200" :items-per-page="10" v-model="page" />

  <!-- 200 items at 25 per page = 8 pages -->
  <Pagination.Root :size="200" :items-per-page="25" v-model="page" />
</template>
<script setup lang="ts">
  import { Pagination } from '@vuetify/v0'
  import { shallowRef } from 'vue'

  const model = shallowRef(4)
</script>

<template>
  <Pagination.Root
    v-slot="{ items }"
    v-model="model"
    class="flex items-center justify-center gap-1"
    :size="200"
  >
    <Pagination.First class="w-9 h-9 rounded border border-divider flex items-center justify-center bg-surface hover:bg-surface-tint data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
      «
    </Pagination.First>

    <Pagination.Prev class="w-9 h-9 rounded border border-divider flex items-center justify-center bg-surface hover:bg-surface-tint data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
      ‹
    </Pagination.Prev>

    <template v-for="(item, index) in items" :key="index">
      <Pagination.Ellipsis
        v-if="item.type === 'ellipsis'"
        class="w-9 h-9 flex items-center justify-center text-on-surface opacity-60"
      />

      <Pagination.Item
        v-else
        class="w-9 h-9 rounded border border-divider flex items-center justify-center bg-surface hover:bg-surface-tint data-[selected]:bg-primary data-[selected]:text-on-primary data-[selected]:border-primary data-[selected]:hover:bg-primary"
        :value="item.value as number"
      >
        {{ item.value }}
      </Pagination.Item>
    </template>

    <Pagination.Next class="w-9 h-9 rounded border border-divider flex items-center justify-center bg-surface hover:bg-surface-tint data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
      ›
    </Pagination.Next>

    <Pagination.Last class="w-9 h-9 rounded border border-divider flex items-center justify-center bg-surface hover:bg-surface-tint data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
      »
    </Pagination.Last>
  </Pagination.Root>
</template>

Anatomy

vue
<script setup lang="ts">
  import { Pagination } from '@vuetify/v0'
</script>

<template>
  <Pagination.Root>
    <Pagination.Status />

    <Pagination.First />

    <Pagination.Prev />

    <Pagination.Ellipsis />

    <Pagination.Item />

    <Pagination.Next />

    <Pagination.Last />
  </Pagination.Root>
</template>
Warning

For responsive sizing to work accurately, all pagination buttons must have the same width. The component measures a sample button and uses that width to calculate how many buttons fit. If buttons have variable widths (e.g., single-digit “1” vs double-digit “50”), the calculation will be inaccurate and items may overflow or leave excess space.

Accessibility

The Pagination component renders semantic HTML and manages ARIA attributes automatically:

  • Wraps controls in a <nav> element whose aria-label defaults to "Pagination" (localizable via the Pagination.label key) for landmark navigation

  • Current page button is marked with aria-current="page" so screen readers announce it as the active page

  • Arrow keys navigate between page buttons; Enter and Space select the focused page

  • Page changes are announced to screen readers via aria-live region updates

For custom implementations, use renderless mode and bind the attrs slot prop to preserve all ARIA attributes:

vue
<template>
  <Pagination.Root v-slot="{ attrs }" renderless>
    <nav v-bind="attrs">
      <!-- Custom pagination controls -->
    </nav>
  </Pagination.Root>
</template>

FAQ

Discord
Need help? Join our community for support and discussions ↗
Was this page helpful?

© 2016-1970 Vuetify, LLC
Services
Ctrl+/