Skip to main content

Pagination

This page shows you how to add pagination to your loops.

How it works

The Loop block can assign a query name to its query. Once named, you can reference the query results — including pagination — after the loop. For example, if you set the query name to products:

{% for product in get_posts({'post_type': 'product', 'posts_per_page': 12}) %}
<h2>{{ product.title }}</h2>
{% endfor %}

{{ products.pagination }}

If you need pagination or a total count before the loop, use a Variable block instead:

{% set products = get_posts({'post_type': 'product', 'posts_per_page': 12}) %}

<p>{{ products.found_posts }} products</p>
{{ products.pagination }}

{% for post in products %}
<h2>{{ post.title }}</h2>
{% endfor %}

Simple output

The quickest way — outputs default pagination markup:

{{ products.pagination }}

Place it before the loop, after the loop, or both.

Custom pagination

Loop over pagination.pages for full control:

<nav class="pagination">
{% if products.pagination.prev %}
<a href="{{ products.pagination.prev.link }}">Previous</a>
{% endif %}

{% for page in products.pagination.pages %}
{% if page.current %}
<span class="current">{{ page.title }}</span>
{% endif %}

{% if not page.current %}
<a href="{{ page.link }}">{{ page.title }}</a>
{% endif %}
{% endfor %}

{% if products.pagination.next %}
<a href="{{ products.pagination.next.link }}">Next</a>
{% endif %}
</nav>

Query properties

These are available on any variable that holds a query result:

PropertyTypeDescription
products.found_postsintTotal items matching the query across all pages
products.paginationobjectPagination object (render directly or access sub-properties)
products.pagination.prevobject or nullPrevious page
products.pagination.nextobject or nullNext page
products.pagination.pagesarrayAll page objects

Page object

Each item in pagination.pages:

PropertyTypeDescription
page.linkstringURL to the page
page.titlestringPage number or label
page.currentboolTrue if this is the current page

Full example

{% set products = get_posts({'post_type': 'product', 'posts_per_page': 10}) %}

<header>
<h1>Products ({{ products.found_posts }})</h1>
{{ products.pagination }}
</header>

{% for post in products %}
<article>
<h2>{{ post.title }}</h2>
<p>{{ post.excerpt }}</p>
</article>
{% endfor %}

<footer>
{{ products.pagination }}
</footer>

Main query pagination

For archives and search results, use the posts variable to access the main WordPress query:

{% set archive = posts %}

<h1>Archive ({{ archive.found_posts }} posts)</h1>

{% for post in archive %}
<h2>{{ post.title }}</h2>
{% endfor %}

{{ archive.pagination }}
Common mistake

A Variable block is only needed when you want pagination before the loop. If pagination comes after, assign a query name in the Loop block and reference it directly — no Variable block required.

Next steps

  • Loop — loop concept and data sources
  • Query Posts — all query arguments for posts and custom post types
  • Variable block — store queries for reuse