🇺🇦🇺🇦🇺🇦 Stand with Ukraine 🇺🇦🇺🇦🇺🇦
Eleventy
The possum is Eleventy’s mascot
Eleventy Documentation
Menu
Eleventy 5.81s
Astro 12.52s

Pagination Navigation

Contents

How to create a list of links to every paginated page on a pagination template.

Paginating over an Array Jump to heading

Consider the following example paginating our testdata array:

View this example in: Liquid Nunjucks 11ty.js Handlebars
Syntax Liquid
---
pagination:
data: testdata
size: 2
testdata:
- item1
- item2
- item3
- item4
- item5
- item6
---
{% comment %}pagination.items has the data for the current page{% endcomment %}
Syntax Nunjucks
---
pagination:
data: testdata
size: 2
testdata:
- item1
- item2
- item3
- item4
- item5
- item6
---
{# pagination.items has the data for the current page #}

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

The above example would make three different output files from the template.

But to create a series of links to each of these paginated output templates, we’ll want to use our pagination.pages entries , an array of the pagination.items for each page.

A good way to think about it:

INFO:
While the above example pages over an array of data, the code provided here will operate the same for any paginated data (including objects)!

Starter Example Jump to heading

To create an accessible navigation structure, we want to do our research first!

Alright, you definitely read all of those right? 😇 Here’s some accessible code you definitely would have written yourself after reading those wonderful resources:

View this example in: Liquid Nunjucks 11ty.js Handlebars
Filename starter.liquid
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
{%- for pageEntry in pagination.pages %}
<li><a href="{{ pagination.hrefs[ forloop.index0 ] }}"{% if page.url == pagination.hrefs[ forloop.index0 ] %} aria-current="page"{% endif %}>Page {{ forloop.index }}</a></li>
{%- endfor %}
</ol>
</nav>
Filename starter.njk
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
{%- for pageEntry in pagination.pages %}
<li><a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if page.url == pagination.hrefs[ loop.index0 ] %} aria-current="page"{% endif %}>Page {{ loop.index }}</a></li>
{%- endfor %}
</ol>
</nav>
Filename starter.11ty.js
exports.render = function(data) {
return `<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
${data.pagination.pages.map(function (item, index) {
return `<li><a href="${data.pagination.hrefs[index]}" ${data.pagination.hrefs[index] ? 'aria-current="page"' : "" }>Page ${index + 1}</a></li>`;
}).join("");}

</ol>
</nav>
`
;
};

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

For our example, this code will output the following markup for our example (on the first page):

Syntax HTML
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li><a href="/test/" aria-current="page">Page 1</a></li>
<li><a href="/test/1/">Page 2</a></li>
<li><a href="/test/2/">Page 3</a></li>
</ol>
</nav>
INFO:
HTML tip: make sure the id attribute used on your heading (id="my-pagination") is unique to your page!

Accessing the Original Paginated Content Jump to heading

Say you want to output something from the paginated data instead of bland Page 1, Page 2, etc. links. For that we need to access the original data!

When Paginating Arrays Jump to heading

Syntax YAML
testdata:
- item1
- item2
- item3
- item4
- item5
- item6
View this example in: Liquid Nunjucks 11ty.js Handlebars

When Paginating Object Literals Jump to heading

Syntax YAML
testdata:
key1: item1
key2: item2
key3: item3
key4: item4
key5: item5
key6: item6
View this example in: Liquid Nunjucks 11ty.js Handlebars

You’ll probably also want to add some kind of visual styling to indicate that the user is on the current page. For this let’s use a light background-color.

Syntax CSS
[aria-current] {
background-color: #eee;
}
INFO:
A Tip to avoid something that annoys Zach™: If you use something like font-weight here make sure the change in text size for the current page doesn’t make your navigation shift around between pages! This is especially important if your navigation links are displayed side-by-side on the same line.

Note that if the current page (page.url) is the first or last in the set, we won’t output links.

View this example in: Liquid Nunjucks 11ty.js Handlebars

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

Filename nextprev.njk
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>{% if pagination.href.previous %}<a href="{{ pagination.href.previous }}">Previous</a>{% else %}Previous{% endif %}</li>
{%- for pageEntry in pagination.pages %}
<li><a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if page.url == pagination.hrefs[ loop.index0 ] %} aria-current="page"{% endif %}>Page {{ loop.index }}</a></li>
{%- endfor %}
<li>{% if pagination.href.next %}<a href="{{ pagination.href.next }}">Next</a>{% else %}Next{% endif %}</li>
</ol>
</nav>
Filename nextprev.11ty.js
exports.render = function(data) {
return `<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>
${data.pagination.href.previous ? `<a href="${data.pagination.href.previous}">Previous</a>` : `Previous`}</li>
${data.pagination.pages.map(function (item, index) {
return `<li><a href="${data.pagination.hrefs[index]}" ${data.pagination.hrefs[index] ? 'aria-current="page"' : "" }>Page ${index + 1}</a></li>`;
}).join("");}

<li>
${data.pagination.href.next ? `<a href="${data.pagination.href.next}">Next</a>` : `Next`}</li>
</ol>
</nav>
`
;
};

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

For clarity here, we’re omitting the previous and next links from the previous section. Note the code below to show the links only if pagination.href.first and pagination.href.last don’t match the current page.url.

View this example in: Liquid Nunjucks 11ty.js Handlebars

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

Filename firstlast.njk
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>{% if page.url != pagination.href.first %}<a href="{{ pagination.href.first }}">First</a>{% else %}First{% endif %}</li>
{%- for pageEntry in pagination.pages %}
<li><a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if page.url == pagination.hrefs[ loop.index0 ] %} aria-current="page"{% endif %}>Page {{ loop.index }}</a></li>
{%- endfor %}
<li>{% if page.url != pagination.href.last %}<a href="{{ pagination.href.last }}">Last</a>{% else %}Last{% endif %}</li>
</ol>
</nav>
Filename firstlast.11ty.js
exports.render = function(data) {
return `<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>
${data.page.url === data.pagination.href.first ? `<a href="${data.pagination.href.first}">First</a>` : `First`}</li>
${data.pagination.pages.map(function (item, index) {
return `<li><a href="${data.pagination.hrefs[index]}" ${data.pagination.hrefs[index] ? 'aria-current="page"' : "" }>Page ${index + 1}</a></li>`;
}).join("");}

<li>
${data.page.url === data.pagination.href.last ? `<a href="${data.pagination.href.last}">Last</a>` : `Last`}</li>
</ol>
</nav>
`
;
};

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

Put It All Together Jump to heading

Here’s the final pagination navigation template code, pieced together:

View this example in: Liquid Nunjucks 11ty.js Handlebars

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

Filename combined.njk
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>{% if page.url != pagination.href.first %}<a href="{{ pagination.href.first }}">First</a>{% else %}First{% endif %}</li>
<li>{% if pagination.href.previous %}<a href="{{ pagination.href.previous }}">Previous</a>{% else %}Previous{% endif %}</li>
{%- for pageEntry in pagination.pages %}
<li><a href="{{ pagination.hrefs[ loop.index0 ] }}"{% if page.url == pagination.hrefs[ loop.index0 ] %} aria-current="page"{% endif %}>Page {{ loop.index }}</a></li>
{%- endfor %}
<li>{% if pagination.href.next %}<a href="{{ pagination.href.next }}">Next</a>{% else %}Next{% endif %}</li>
<li>{% if page.url != pagination.href.last %}<a href="{{ pagination.href.last }}">Last</a>{% else %}Last{% endif %}</li>
</ol>
</nav>
Filename combined.11ty.js
exports.render = function(data) {
return `<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>
${data.page.url === data.pagination.href.first ? `<a href="${data.pagination.href.first}">First</a>` : `First`}</li>
<li>
${data.pagination.href.previous ? `<a href="${data.pagination.href.previous}">Previous</a>` : `Previous`}</li>
${data.pagination.pages.map(function (item, index) {
return `<li><a href="${data.pagination.hrefs[index]}" ${data.pagination.hrefs[index] ? 'aria-current="page"' : "" }>Page ${index + 1}</a></li>`;
}).join("")}

<li>
${data.pagination.href.next ? `<a href="${data.pagination.href.next}">Next</a>` : `Next`}</li>
<li>
${data.page.url === data.pagination.href.last ? `<a href="${data.pagination.href.last}">Last</a>` : `Last`}</li>
</ol>
</nav>
`
;
};

This example has not yet been added—you can swap to another template language above! Or maybe you want to contribute it? Edit this page

Alright, you’ve copied the above—but don’t leave yet—your work is not done (sorry)! You still need to:

INFO:
HTML tip: You might be tempted to use role="navigation" here, but it’s superfluous when using <nav>.
INFO:
Accessibility tip: if you style this list with list-style-type: none, read this article about VoiceOver

All of the above will output the following HTML for our example (on the first page of the set):

Syntax HTML
<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
<li>First</li>
<li>Previous</li>
<li><a href="/test-array/" aria-current="page">Page 1</a></li>
<li><a href="/test-array/1/">Page 2</a></li>
<li><a href="/test-array/2/">Page 3</a></li>
<li><a href="/test-array/1/">Next</a></li>
<li><a href="/test-array/2/">Last</a></li>
</ol>
</nav>