DiversIT Europe
Previous Home Next Sep 4, 2017 Pagination on a Jekyll site Tags: jekyll

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:

starting trail and in middle trail

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: '//', '/' }}">&lt;&lt;</a>
    </li>
    {%- endif -%}

    {%- if paginator.previous_page -%}
    <li class="previous">
        <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&lt;</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: '//', '/' }}">&gt;</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: '//', '/' }}">&gt;&gt;</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');
        }
    }
}