“Previous” and “next” in Eleventy

A brief description of code that easily enables this oft-requested feature.

2019-12-23

This one will be uncharacteristically short, you’ll be happy to know. But I learned something yesterday that I just have to share with my fellow and sister Eleventy aficionados out there.

In reading not only the Eleventy docs but also numerous “how-to” articles by various Eleventy users, I’d been unable to learn a way to automate the inclusion of “Previous post” and “Next post” links, such as those you see at the bottom of each of my posts.

(Note that all the code herein assumes you assign each post a post tag in its front matter, as shown in this example.)

You see, the most workable method I’d found so far from among the starter projects and others listed on the Eleventy site was quite manual: give each post an index number in its front matter (idx: 41, for example), and then find it that way. For example (WARNING: if you’re looking through this in a hurry, THIS ISN’T THE FINAL ANSWER!):

{% if collections.post[idx] %}
	<p class="ctr">
		<strong>Next</strong>:
		<a class="next" href="{{ collections.post[idx].url }}">{{ collections.post[idx].data.title }}</a>
	</p>
{% endif %}
{% if collections.post[idx-2] %}
	<p class="ctr">
		<strong>Previous</strong>:
		<a class="previous" href="{{ collections.post[idx-2].url }}">{{ collections.post[idx-2].data.title }}</a>
	</p>
{% endif %}

Yes, it worked, but I wanted a “set-and-forget” method — something that would survive post deletions or any other possibility that might come up, not to mention a simple human failure to give the correct and unique idx assignment to a new post. And so did others.

I suspected there was a solution in the Eleventy API that was so ridiculously simple that, if I found it, I’d have two immediate reactions: joy from finding it and pain from the slap I’d give myself on top of the head for having missed it.

Early yesterday morning, after having asked about an earlier proposed answer to the question, I saw a reply that quickly proved to be The Answer (THIS one is what you’re seeking, folks) from Pascal Widdershoven in the form of a wonderfully simple and elegant addition to one’s .eleventy.js file:

eleventyConfig.addCollection("posts", function(collection) {
	const coll = collection.getFilteredByTag("posts");

	for(let i = 0; i < coll.length ; i++) {
		const prevPost = coll[i-1];
		const nextPost = coll[i + 1];

		coll[i].data["prevPost"] = prevPost;
		coll[i].data["nextPost"] = nextPost;
	}

	return coll;
});

Ah. A thing of beauty.

Once you’ve added that to your site’s .eleventy.js file, all you have to do is put something like the following in the appropriate place in your Eleventy template for single posts (this is in Nunjucks, so please adjust according to the template language of your choice):

	{% if nextPost.url %}
		<p class="ctr">
			<strong>Next</strong>:
			<a class="next" href="{{ nextPost.url }}">{{ nextPost.data.title }}</a>
		</p>
	{% endif %}
	{% if prevPost.url %}
		<p class="ctr">
			<strong>Previous</strong>:
			<a class="previous" href="{{ prevPost.url }}">{{ prevPost.data.title }}</a>
		</p>
	{% endif %}

And, no, I didn’t swat myself, but I did get the joy.

Thank you, Mr. Widdershoven, for the eye-opener! This has been an FAQ in the truest sense of that term, and you got us over the goal line. As I gratefully told you yesterday: “You da man!”

Note from the future: This ceased to be necessary as of the 2020 release of Eleventy 0.11.0, which added universal filters for “next” and “previous” collection items.

Reply via email
View comments