Pagination is the 11ty term for producing multiple files from one input file.
It operates on an array of data.
The size variable specifies the number of
array elements to be rendered on each page.
Often it is set to 1 to render each element on a separate page.
The array data can come from anywhere in the data cascade.
By default the URL for each page produced ends with a slash and a page number.
For example:
pagination:
data: employees # data over which to paginate
size: 7 # number of employees per page
The global variable pagination holds related data.
pagination.dataholds the value of the paginationdataproperty from the front matter.pagination.pagesholds an array of items for each page. When the size is one the array holds each page item. When the size is greater than one it holds arrays of the items on each page. Whendatais an object rather than an array, it holds keys instead of items.pagination.itemsis an array of the objects to be rendered on the current page.pagination.pages.lengthis the number of pages.pagination.pageNumberholds the zero-based index of the current page.pagination.firstPageLinkholds the URL of the first page (aliasfirst).pagination.firstPageHrefis the same, but omitsindex.htmlat end.pagination.previousPageLinkholds the URL of the previous page (aliasprevious).pagination.previousPageHrefis the same, but omitsindex.htmlat end.pagination.nextPageLinkholds the URL of the next page; (aliasnext).pagination.nextPageHrefis the same, but omitsindex.htmlat end.pagination.lastPageLinkholds the URL of the last page (aliaslast).pagination.lastPageHrefis the same, but omitsindex.htmlat end.pagination.pageLinksholds an array of all the page links (aliaslinks).pagination.hrefholds an object with keys “previous”, “next”, “first”, and “last” whose values are those hrefs.pagination.hrefsholds an array of all the page hrefs.
The URL for each page is /{pagination.data}/{zero-based-index}.
The URL for the first page page is /{data-name}, omitting an index.
The URL /{data-name}/0 is not valid.
pagination.items holds the current page item when the size is 1
or an array of the current page items when size is greater than 1.
To add an alias for this add an alias property
to the pagination front matter.
For example:
pagination:
...
alias: items
With this alias in place, we can iterate over items
instead of pagination.items to render all the items on the current page.
To display “Page m of n”:
<div>
Page {{pagination.pageNumber + 1}} of {{pagination.pages.length}}
</div>
To render links to the first, previous, next, and last pages so each is only rendered when it makes sense:
<nav class="pagination">
<ol>
{% if pagination.pageNumber > 0 %}
<li><a href="{{pagination.href.first}}">First</a></li>
{% endif %}
{% if pagination.href.previous %}
<li><a href="{{pagination.href.previous}}">Prev</a></li>
{% endif %}
{% if pagination.href.next %}
<li><a href="{{pagination.href.next}}">Next</a></li>
{% endif %}
{% if pagination.pageNumber < pagination.pages.length - 1 %}
<li><a href="{{pagination.href.last}}">Last</a></li>
{% endif %}
</ol>
</nav>
To render links to all the pages except the current by number:
<nav class="pagination">
<ol>
{% for href in pagination.hrefs %}
{%if loop.index0 !== pagination.pageNumber %}
<li><a href="{{href}}">Page {{ loop.index }}</a></li>
{% endif %}
{% endfor %}
</ol>
</nav>
Note that Nunjucks provides the variable loop that holds
an object with the properties index (1-based) and index0 (0-based).
These hold the current loop index.
To style the anchor tags as buttons:
.pagination {
background-color: transparent;
}
.pagination ol {
display: flex;
list-style: none;
padding: 0.5rem 0; /* to match "a" padding below */
}
.pagination a {
border: solid gray 1px;
border-radius: 0.5rem;
padding: 0.5rem;
text-decoration: none;
}
To style the anchor for the current page differently that the others,
define a CSS rule for a.current and
set the class on the a elements as follows:
<a
class="{{'current' if loop.index0 === pagination.pageNumber else ''}}"
href="{{href}}"
>
To paginate data in reverse order,
add the reverse property to the pagination front matter.
pagination:
...
reverse: true
When data is an object rather than an array,
the items will be keys instead of items.
To change this so the items are the property values,
add the resolve property to the pagination front matter.
pagination:
...
resolve: values
To produce different data to be paginated from existing data,
use the before front matter property whose value is
a JavaScript function that takes the data and returns new data.
This can create new data to paginate by filtering, sort, and transforming.
Using this requires all the front matter
to be converted from YAML to JavaScript.
For example, the following filters the employees
so only those age 50 and older are retained
and it makes their names all uppercase:
---js
{
layout: 'employees-layout.njk',
title: 'Employees',
pagination: {
data: 'employees',
size: 7,
alias: 'items',
before(employees) {
return employees.
filter(emp => emp.employee_age >= 50).
map(emp => ({
...emp,
employee_name: emp.employee_name.toUpperCase()
}));
}
}
}
---
To change the paths of the files produced for each page, specify a permalink.
For example, if the file employees.njk uses pagination then
it would normally generate files like _site/employees/2/index.html
where 2 is a page number.
To change this so it generates files like
_site/workers/group-2/index.html, add the following front matter:
permalink: 'workers/group-{{pagination.pageNumber}}/index.html'
When a template uses pagination and gets data from a REST service as shown above, the REST service is invoked once, then again for each page. So if pagination results in three pages, there will be four calls to the REST service. TODO: Why is this? TODO: See the issue you created about pagination and .11ty.js files TODO: at https://github.com/11ty/eleventy/issues/919.