skip to content

In Laravel 13, how do you control the HTML that $paginator->links() renders: the view, the CSS framework and how many page links appear?

level: middleimportance: nice to knowfreq 24%

answer

  1. Tailwind views by default
  2. Paginator::useBootstrapFive() in boot()
  3. vendor:publish --tag=laravel-pagination
  4. onEachSide(3) is the default window
  5. 13: pagination::default renamed bootstrap-3

basics

~20 s

links() renders the Tailwind pagination view by default. Pass a view name to links(), set a default with Paginator::defaultView() or useBootstrapFive(), publish the views to edit them, and use onEachSide() to change how many page links surround the current page.

solid answer

~30 s

By default `links()` renders `pagination::tailwind` for `paginate()` and `pagination::simple-tailwind` for `simplePaginate()` and `cursorPaginate()`. You can pass a view per call, `links('partials.pager')`, or change the defaults in `AppServiceProvider::boot()` with `Paginator::defaultView()` / `defaultSimpleView()`, or with `Paginator::useBootstrapFive()` or `useBootstrapFour()`. `php artisan vendor:publish --tag=laravel-pagination` copies the views to `resources/views/vendor/pagination` so you can edit them. On a `paginate()` result, `onEachSide(n)` sets how many numbered links appear either side of the current page; the default is 3. In Laravel 13 the Bootstrap 3 views are named `pagination::bootstrap-3` and `pagination::simple-bootstrap-3`; before 13 they were `pagination::default` and `pagination::simple-default`.

code

php · 14 lines
php
<?php

namespace App\Providers;

use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Paginator::useBootstrapFive();
    }
}

go deeper

for a junior

Recall that links() renders Tailwind by default and that useBootstrapFive() or a view name passed to links() changes it.

for a middle

Explain default versus simple views, publishing with --tag=laravel-pagination, and how onEachSide() shapes the URL window.

for a senior

Plan the upgrade impact of the Laravel 13 view rename and keep published views in step with framework changes.

for a principal

Decide whether the team owns bespoke pagination markup or stays on framework views, weighing design control against upgrade cost.

## Where the HTML comes from A Laravel paginator renders its links through an ordinary Blade view. `$paginator->links()` (an alias of `render()`) chooses the view in this order: 1. a view name passed to the call, `links('partials.pager', ['label' => 'Activities'])`, with optional extra data; 2. otherwise the class default: `Paginator::$defaultView` for a `LengthAwarePaginator` (from `paginate()`), and `Paginator::$defaultSimpleView` for a `Paginator` (from `simplePaginate()`) or a `CursorPaginator` (from `cursorPaginate()`). The defaults are `pagination::tailwind` and `pagination::simple-tailwind`. With Tailwind 4, the skeleton's CSS already points Tailwind at the framework's pagination views so their classes are generated. ## Switching frameworks or views globally Call one of these in `App\Providers\AppServiceProvider::boot()`: | Call | Numbered view | Simple view | |---|---|---| | `Paginator::useTailwind()` | `pagination::tailwind` | `pagination::simple-tailwind` | | `Paginator::useBootstrapFive()` | `pagination::bootstrap-5` | `pagination::simple-bootstrap-5` | | `Paginator::useBootstrapFour()` | `pagination::bootstrap-4` | `pagination::simple-bootstrap-4` | | `Paginator::useBootstrap()` | same as `useBootstrapFour()` | same as `useBootstrapFour()` | | `Paginator::useBootstrapThree()` | `pagination::bootstrap-3` | `pagination::simple-bootstrap-3` | | `Paginator::defaultView('x')` / `defaultSimpleView('y')` | your view | your view | A `semantic-ui` view also ships with the framework. ## Editing the markup `php artisan vendor:publish --tag=laravel-pagination` copies every pagination view into `resources/views/vendor/pagination`. Laravel's view finder checks that directory before the framework's own, so editing `tailwind.blade.php` there changes every `links()` call without touching controllers. Inside the view you have the paginator (`$paginator`) and, for numbered views, the `$elements` array of page links and `...` separators. ## Writing your own view A custom pagination view receives two variables: - `$paginator`, with helpers such as `hasPages()`, `onFirstPage()`, `hasMorePages()`, `currentPage()`, `previousPageUrl()` and `nextPageUrl()`; - `$elements`, for numbered views only: an array whose entries are either an array of `page => url` pairs or the string `...` for a gap. A minimal numbered view therefore: 1. renders nothing unless `$paginator->hasPages()`; 2. prints a previous link, disabled when `onFirstPage()` is true; 3. loops `$elements`, printing `...` for strings and a link per page otherwise, marking the one equal to `currentPage()`; 4. prints a next link, disabled unless `hasMorePages()` is true. Simple views skip step 3. Keeping the view to these helpers means it works with every paginator of that kind. ## The link window For a `paginate()` result, the numbered links are computed by a **URL window** around the current page. `onEachSide(n)` sets how many page links appear on each side of the current page; the default property value is 3. - When the last page is small relative to the window (fewer than `2n + 8` pages), every page is listed. - Otherwise the first two and last two pages are shown as caps, with `...` separators and a sliding group of `n` pages each side of the current one. - Near either end, a longer run of pages replaces the slider on that side. `onEachSide()` has no visible effect on `simplePaginate()` and `cursorPaginate()`, whose views render only previous and next. ## What changed in Laravel 13 The Laravel 13 upgrade guide renamed the internal Bootstrap 3 view names to make them explicit: - `pagination::default` became `pagination::bootstrap-3`; - `pagination::simple-default` became `pagination::simple-bootstrap-3`. Tailwind remains the default. An app that referenced the old names directly, for example `links('pagination::default')` or a `defaultView('pagination::default')` call, must update them; `Paginator::useBootstrapThree()` already points at the new names. ## Interview angle The practical answer is: keep the default Tailwind view if you use Tailwind; switch with `useBootstrapFive()` if you use Bootstrap; publish and edit the views for bespoke markup; and use `onEachSide()` to trim the number of links on narrow screens. Mentioning the Laravel 13 rename shows you have upgraded a real app.

  • Your Laravel 12 app calls links('pagination::default') and breaks after upgrading to 13. Why?
    Laravel 13 renamed the Bootstrap 3 views to `pagination::bootstrap-3` and `pagination::simple-bootstrap-3`, so `pagination::default` no longer exists. Change the reference, or call `Paginator::useBootstrapThree()`, which uses the new names.
  • Can you call onEachSide() on a cursorPaginate() result?
    No. `CursorPaginator` does not define `onEachSide()`; the call is forwarded to its item collection and fails with a `BadMethodCallException`. A cursor paginator has no page numbers to window, and its default view is the simple one with previous and next links only.

The paginator is like a lift's floor panel: the building decides which floors exist, and onEachSide() only decides how many neighbouring buttons are printed around the one you are on.

saying these in an interview costs you the question

  • Laravel's default pagination view is Bootstrap
  • pagination::default is still the Bootstrap 3 view name in Laravel 13
  • onEachSide() changes how many rows each page holds
  • Custom pagination markup requires extending the paginator class
  • useBootstrap() selects the Bootstrap 5 views