{% paginate %}

This document is for a version of Craft CMS that is no longer supported. Please refer to the latest version →

This tag makes it easy to paginate a set of elements across multiple pages.

{% paginate craft.entries.section('blog').limit(10) as pageInfo, pageEntries %}

{% for entry in pageEntries %}
  <article>
    <h1>{{ entry.title }}</h1>
    {{ entry.body }}
  </article>
{% endfor %}

{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous Page</a>{% endif %}
{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next Page</a>{% endif %}

Paginated URLs will be identical to the first page’s URL, except that “/p_X_” will be appended to the end (where X is the page number), e.g. http://my-project.tld/news/p2.

You can use the pageTrigger config setting to customize what comes before the actual page number in your URLs. For example you could set it to 'page/', and your paginated URLs would start looking like http://my-project.tld/news/page/2.

Only a single {% paginate %} tag should be used per request.

# Parameters

The {% paginate %} tag has the following parameters:

# Element criteria

The first thing you pass into the {% paginate %} tag is an ElementCriteriaModel object, which defines all of the elements that should be paginated. Use the limit parameter to define how many elements should show up per page.

This parameter needs to be an actual ElementCriteriaModel object; not an array of elements. So don’t call find() on the object.

# as

Next up you need to type “as”, followed by one or two variable names:

  • as pageInfo, pageEntries
  • as pageEntries

The actual variable name(s) are up to you, however if you only specify one variable name here, the pageInfo variable will be called “paginate” by default.

Here’s what they get set to:

  • pageInfo gets set to a Craft\PaginateVariable (opens new window) object, which provides info about the current page, and some helper methods for creating links to other pages (more details below).
  • pageEntries gets set to an array of the elements that belong to the current page.

# Showing the elements

The {% paginate %} tag won’t actually output the current page’s elements for you – it will only give you an array of the elements that should be on the current page (referenced by the variable you defined in the as parameter.)

Following your {% paginate %} tag, you will need to loop through this page’s elements using a for (opens new window) tag.

{% paginate craft.entries.section('blog').limit(10) as pageEntries %}

{% for entry in pageEntries %}
  <article>
    <h1>{{ entry.title }}</h1>
    {{ entry.body }}
  </article>
{% endfor %}

# The pageInfo variable

The pageInfo variable (or whatever you’ve called it, or paginate by default) provides the following properties and methods:

  • pageInfo.first – The offset of the first element on the current page.
  • pageInfo.last – The offset of the last element on the current page.
  • pageInfo.total – The total number of elements across all pages
  • pageInfo.currentPage – The current page number.
  • pageInfo.totalPages – The total number of pages.
  • pageInfo.prevUrl – The URL to the previous page, or null if you’re on the first page.
  • pageInfo.nextUrl – The URL to the next page, or null if you’re on the last page.
  • pageInfo.firstUrl – The URL to the first page.
  • pageInfo.lastUrl – The URL to the last page.
  • pageInfo.getPageUrl( page ) – Returns the URL to a given page number, or null if the page doesn’t exist.
  • pageInfo.getPrevUrls( [dist] ) – Returns an array of URLs to the previous pages, with keys set to the page numbers. The URLs are returned in ascending order. You can optionally pass in the maximum distance away from the current page the function should go.
  • pageInfo.getNextUrls( [dist] ) – Returns an array of URLs to the next pages, with keys set to the page numbers. The URLs are returned in ascending order. You can optionally pass in the maximum distance away from the current page the function should go.
  • pageInfo.getRangeUrls( start, end ) – Returns an array of URLs to pages in a given range of page numbers, with keys set to the page numbers.

The pageInfo variable gives you lots of options for building the pagination navigation that’s right for you. Here are a few common examples.

If you just want simple Previous Page and Next Page links to appear, you can do this:

{% paginate craft.entries.section('blog').limit(10) as pageInfo, pageEntries %}

{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous Page</a>{% endif %}
{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next Page</a>{% endif %}

Note that we’re wrapping those links in conditionals because there won’t always be a previous or next page.

You can add First Page and Last Page links into the mix, you can do that too:

{% paginate craft.entries.section('blog').limit(10) as pageInfo, pageEntries %}

<a href="{{ pageInfo.firstUrl }}">First Page</a>
{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous Page</a>{% endif %}
{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next Page</a>{% endif %}
<a href="{{ pageInfo.lastUrl }}">Last Page</a>

There’s no reason to wrap those links in conditionals since there will always be a first and last page.

If you want to create a list of nearby pages, perhaps surrounding the current page number, you can do that too!

{% paginate craft.entries.section('blog').limit(10) as pageInfo, pageEntries %}

<a href="{{ pageInfo.firstUrl }}">First Page</a>
{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous Page</a>{% endif %}

{% for page, url in pageInfo.getPrevUrls(5) %}
  <a href="{{ url }}">{{ page }}</a>
{% endfor %}

<span class="current">{{ pageInfo.currentPage }}</span>

{% for page, url in pageInfo.getNextUrls(5) %}
  <a href="{{ url }}">{{ page }}</a>
{% endfor %}

{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next Page</a>{% endif %}
<a href="{{ pageInfo.lastUrl }}">Last Page</a>

In this example we’re only showing up to five page links in either direction of the current page. If you’d prefer to show more or less, just change the numbers that are passed into getPrevUrls() and getNextUrls(). You can also choose to not pass any number in at all, in which case all previous/next page URLs will be returned.