Skip to main content

What is pagination

Laravel’s pagination is integrated with the query builder and Eloquent ORM, so you can start using it without any configuration. The current page is automatically detected from the page query parameter on the HTTP request and is also automatically appended to the generated links. The default HTML supports Tailwind CSS, and Bootstrap CSS is available as an option.

Three pagination methods

Basic usage

Query builder pagination

Eloquent pagination

simplePaginate

When you don’t need a total-count query (displaying only “Previous” and “Next” links), simplePaginate() is more efficient.
Choose simplePaginate() when you don’t need to display “X of Y total.” paginate() runs an additional COUNT(*) query, so simplePaginate() is faster.

cursorPaginate (cursor pagination)

Cursor pagination uses a WHERE clause instead of OFFSET, delivering high performance on large datasets. It’s especially well-suited to infinite-scroll UIs.
The generated URLs contain a cursor string instead of a page number.
orderBy is required to use cursor pagination. Also, the sorting columns must belong to the table you’re paginating.

OFFSET vs cursor comparison

Cursor pagination makes effective use of indexes and is much less likely to duplicate or skip records even when data is frequently added or removed. However, it cannot generate numbered page links—only “Previous” and “Next.”

Controller implementation

The links() method automatically generates HTML for the page links. It shows three pages before and three pages after the current page. Use onEachSide() to change how many page links to show before and after the current page.

Accepting per-page count from the request

Displaying multiple paginators on one page

When displaying two paginators on the same screen, both using page conflicts. Change the parameter name via the third argument.

Customizing URLs

Changing the base URL

Appending query parameters

Appending a hash fragment

API responses (JSON output)

If you return a paginator directly from a route or controller, it’s automatically converted to JSON.
The response’s JSON format:

Combining with API resources

To wrap a paginate() result with an API resource collection, pass it to UserResource::collection().
When you pass a paginator to UserResource::collection(), pagination information is automatically added as metadata.
The JSON for cursorPaginate() includes next_cursor and prev_cursor instead of page numbers. API clients use these values as the cursor parameter on the next request.

Custom pagination views

Specifying a view file directly

Changing the default view to a custom file

First publish the official views and then customize.
The following files are generated in resources/views/vendor/pagination/:
  • tailwind.blade.php — Default (for Tailwind CSS)
  • bootstrap-5.blade.php — For Bootstrap 5
  • simple-tailwind.blade.php — For simplePaginate
Edit tailwind.blade.php directly, or create a new view and specify it in AppServiceProvider.

Using Bootstrap CSS

To use Bootstrap instead of Tailwind, configure it in AppServiceProvider’s boot().

Manually creating a paginator

To apply pagination to existing data such as an array, instantiate the paginator class directly.

Commonly used instance methods

Summary

  • paginate() — when you need total count and numbered page links (typical list screens)
  • simplePaginate() — when “Previous” and “Next” only is sufficient (faster)
  • cursorPaginate() — for large datasets, infinite scroll, or when data is written frequently (highest performance)
Just pass the result of paginate() to the view and use links() to output page links. The current page is automatically detected from the page query parameter.
Returning a paginator directly from a route automatically converts it to JSON. To combine with API resources, return UserResource::collection($paginator). The response includes data (an array of records) and various metadata fields.
Last modified on July 13, 2026