On a Jekyll site, pagination can easily be added using a plugin.
The standard (v1) plugin only supports posts and does not support categories and tags. By accident I stumbled upon the jekyll-paginate-v2 plugin. This plugin does support single collection, multiple collections, filtering on categories, tags and locales, etc.
To install the plugin, add the plugin to the Gem
file in the :jekyll-plugins
section:
group :jekyll_plugins do
# (other plugins)
gem 'jekyll-paginate-v2'
end
Also add it to the plugins:
in the _config.yml
:
plugins:
# (other plugins)
- jekyll-paginate-v2
I just added the example site configuration to _config.yml
as well.
On a page where you want to apply pagination, add pagination configuration to the Front Matter section of the page: (e.g. the index.md
page)
pagination:
enabled: true
permalink: '/all/:num/'
This enables pagination for this page, over all posts, and also defines where the pagination pages are generated. Here in the /all/
folder.
To only display posts of a category or tag add:
category: article
or
tag: java, scala
You can also paginate over your own collections. For all options, see the plugin documentation.
The plugin provides a paginator
object. In your layout template, change looping over the collection from site.posts
to paginator.posts
{% for post in paginator.posts %}
<!-- display post -->
{% endfor %}
This is enough for Jekyll to start generating the additional page. Now all you need is to add links, a trail, to them. Something like this:
and
I created a bit of a smart trail which only displays the next/previous and first/last buttons when the not at or near the first or last page.
<paginate>
<ul>
{%- if paginator.page_trail -%}
{% if paginator.page > 2 -%}
<li class="previous">
<a href="{{ paginator.first_page_path | prepend: site.baseurl | replace: '//', '/' }}"><<</a>
</li>
{%- endif -%}
{%- if paginator.previous_page -%}
<li class="previous">
<a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}"><</a>
</li>
{%- endif -%}
{%- if paginator.page_trail -%}
{%- for trail in paginator.page_trail -%}
<li>
<a href="{{ trail.path | prepend: site.baseurl | replace: '//', '/' }}" title="{{trail.title}}" {%- if paginator.page == trail.num -%}class="active"{%- endif -%}>{{ trail.num }}</a>
</li>
{%- endfor -%}
{%- endif -%}
{%- if paginator.next_page -%}
<li class="next">
<a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">></a>
</li>
{%- endif -%}
{%- assign notNearEnd = paginator.page | plus:1 -%}
{%- if notNearEnd < paginator.total_pages -%}
<li class="previous">
<a href="{{ paginator.last_page_path | prepend: site.baseurl | replace: '//', '/' }}">>></a>
</li>
{%- endif -%}
{%- endif -%}
</ul>
</paginate>
Here the SCSS to style the links.
Thanks to Brajeshwar for his Simple Pagination with CSS3
paginate {
margin: 0;
padding: 1em;
text-align: center;
ul {
list-style: none;
margin: 0;
padding: 0;
text-align: center;
// display: inline-block; // an inline-block will allow you to use it with other contents
}
li {
display: inline;
}
a {
border-radius: 3px;
box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px;
margin: 1px 2px;
padding: 5px 10px;
display: inline-block;
border-top: 1px solid #fff;
text-decoration: none;
color: #717171;
font-size: smaller;
font-family: "Helvetica Neueu", Helvetica, Arial, sans-serif;
text-shadow: rgba(255, 255, 255, 1) 0 1px 0;
background-color: #f5f5f5;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#eaeaea));
background-image: -webkit-linear-gradient(top, #f9f9f9, #eaeaea);
background-image: -moz-linear-gradient(top, #f9f9f9, #eaeaea);
background-image: -ms-linear-gradient(top, #f9f9f9, #eaeaea);
background-image: -o-linear-gradient(top, #f9f9f9, #eaeaea);
background-image: linear-gradient(top, #f9f9f9, #eaeaea);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f9f9f9', EndColorStr='#eaeaea');
// reset the margins
&:first-child, &.first { margin-left: 0; }
&:last-child, &.last { margin-right: 0; }
&:hover, &:focus {
border-color: #fff;
background-color: #fdfdfd;
background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#fafafa));
background-image: -webkit-linear-gradient(top, #fefefe, #fafafa);
background-image: -moz-linear-gradient(top, #fefefe, #fafafa);
background-image: -ms-linear-gradient(top, #fefefe, #fafafa);
background-image: -o-linear-gradient(top, #fefefe, #fafafa);
background-image: linear-gradient(top, #fefefe, #fafafa);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#fefefe', EndColorStr='#fafafa');
}
&.more {
box-shadow: 0 0 0 0 transparent;
border: 0 none;
background: transparent;
margin-left: 0;
margin-right: 0;
}
&.active {
box-shadow: rgba(0, 0, 0, 0.75) 0 0 0 0 inset;
border-color: #505050;
color: #f2f2f2;
text-shadow: rgba(0, 0, 0, 1) 0 1px 0;
background-color: #676767;
background-image: -webkit-gradient(linear, left top, left bottom, from(#5f5f5f), to(#5c5c5c));
background-image: -webkit-linear-gradient(top, #5f5f5f, #5c5c5c);
background-image: -moz-linear-gradient(top, #5f5f5f, #5c5c5c);
background-image: -ms-linear-gradient(top, #5f5f5f, #5c5c5c);
background-image: -o-linear-gradient(top, #5f5f5f, #5c5c5c);
background-image: linear-gradient(top, #5f5f5f, #5c5c5c);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#5f5f5f', EndColorStr='#5c5c5c');
}
}
}
.paginate-dark {
a {
box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px;
border-top: 1px solid #62686d;
text-shadow: rgba(0, 0, 0, 0.75) 0 1px 0;
color: #fff;
background-color: #4e5458;
background-image: -webkit-gradient(linear, left top, left bottom, from(#575e63), to(#3f4347));
background-image: -webkit-linear-gradient(top, #575e63, #3f4347);
background-image: -moz-linear-gradient(top, #575e63, #3f4347);
background-image: -ms-linear-gradient(top, #575e63, #3f4347);
background-image: -o-linear-gradient(top, #575e63, #3f4347);
background-image: linear-gradient(top, #575e63, #3f4347);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#575e63', EndColorStr='#3f4347');
&:hover, &:focus {
border-color: #61788a;
background-color: #4d6374;
background-image: -webkit-gradient(linear, left top, left bottom, from(#566f82), to(#3e505e));
background-image: -webkit-linear-gradient(top, #566f82, #3e505e);
background-image: -moz-linear-gradient(top, #566f82, #3e505e);
background-image: -ms-linear-gradient(top, #566f82, #3e505e);
background-image: -o-linear-gradient(top, #566f82, #3e505e);
background-image: linear-gradient(top, #566f82, #3e505e);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#566f82', EndColorStr='#3e505e');
}
&.active {
box-shadow: rgba(0, 0, 0, 0.75) 0 0 0 0 inset;
border-color: #2d3035;
background-color: #303338;
background-image: -webkit-gradient(linear, left top, left bottom, from(#303338), to(#2d3034));
background-image: -webkit-linear-gradient(top, #303338, #2d3034);
background-image: -moz-linear-gradient(top, #303338, #2d3034);
background-image: -ms-linear-gradient(top, #303338, #2d3034);
background-image: -o-linear-gradient(top, #303338, #2d3034);
background-image: linear-gradient(top, #303338, #2d3034);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#303338', EndColorStr='#2d3034');
}
}
}