ssg  
Article Series

Jekyll in General

Jekyll Plain

Preface

Goal: Put a Bootstrap stylesheet, based on our plain pagination.

Source Code

This article use tutor-11 theme. We will create it step by step.

Previous Tutorial

This article is based on our plain pagination.

It is basically just putting on bootstrap stylesheet, so that the pagination looks pretty.


Intro

I hava already make a step by step partial, so you can learn pagination from simple to complete one. For each step, I have made different partial.

Step By Step

We are going to have four steps to achieve this pagination.

  • Layout 01: Simple

  • Layout 02: Number

  • Layout 03: Adjacent

  • Layout 04: Indicator

  • Layout 05: Responsive

  • Layout 06: Screenreader

We have already cover Layout 01 through Layout 04, with Jekyll Plain paginatin without stylesheet. Now we need two more articles:

  1. Pagination: Bootstrap Stylesheet What we need to do now is to refresh our memory from four steps above, all in this article.

  2. Pagination: Bootstrap Responsive Then we will continue with responsive pagination and screenreader, in the next article.

Pagination Plugin

There are two versions of pagination plugin iin Jekyll.

  • Pagination-v1

  • Pagination-v2

I provide both example. But we are going to use pagination-v1 in this article. There is only slight differences.

Configuration

You can read in this article.

Content: Example Article

I provide 17 articles. It should be enough to simulate responsive pagination.

Layout: Blog

Consider review our last layout/index.html laoput. The complete code is as simply as below layout.

---
layout: columns-single
---

{% include pagination-v1/06-screenreader.html %}

{% assign posts = paginator.posts %}
{% include index/blog-list.html %}

{% comment %}

v1: not developed anymore for years
  {% include pagination-v1/01-simple.html %}
  {% include pagination-v1/02-number.html %}
  {% include pagination-v1/03-adjacent.html %}
  {% include pagination-v1/04-indicator.html %}
  {% include pagination-v1/05-responsive.html %}
  {% include pagination-v1/06-screenreader.html %}

v2: not supported by github pages (Without travis)
  {% include pagination-v2/01-simple.html %}
  {% include pagination-v2/02-number.html %}
  {% include pagination-v2/03-adjacent.html %}
  {% include pagination-v2/04-indicator.html %}
  {% include pagination-v2/05-responsive.html %}
  {% include pagination-v2/06-screenreader.html %}

The choice is yours.

{% endcomment %}

You should start with 01-simple.html, and so on.

{% include pagination-v1/01-simple.html %}

Now you should be ready with bootstrap pagination in Jekyll.


1: Simple with Navigation

This preview is what we want to achieve:

Jekyll Bootstrap Pagination: 01 Simple

HTML Preview

Consider fast forward to the last page, so we can have both enabled button and disabled button. We need those two kinds of button as an ideal example. The HTML that we want to achieve in this article, is similar as below.

<nav aria-label="Page navigation">
  <ul class="pagination justify-content-center"> 

    <!-- First Page. -->
      <li class="page-item">
        <a class="page-link" href="/pages" 
           rel="first">First</a>
      </li>

    <!-- Previous Page. -->
      <li class="page-item">
        <a class="page-link" href="/pages/blog-8" 
           rel="prev">Previous</a>
      </li>

    <!-- Indicator Number. -->
    <li class="page-item disabled">
      <span class="page-link">
        Page: 9 of 9</span>
    </li>

    <!-- Next Page. -->
      <li class="page-item disabled">
        <span class="page-link">Next</span>
      </li>

    <!-- Last Page. -->
      <li class="page-item disabled">
        <span class="page-link">Last</span>
      </li>

  </ul>
</nav>

Explanation

Partial Liquid

We will achieve this with liquid code below:

{% capture spaceless %}
  {% assign total_pages = paginator.total_pages %}

  <!-- Get paginate_root from page in frontmatter -->
  {% assign paginate_root = page.paginate_root %}
{% endcapture %}

<nav aria-label="Page navigation">
  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center"> 

    <!-- First Page. -->
    {% unless paginator.page == 1 %}
      {% assign p_first = paginate_root 
                        | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" href="{{ p_first }}" 
           rel="first">First</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">First</span>
      </li>
    {% endunless %}

    <!-- Previous Page. -->
    {% if paginator.previous_page %}
      {% assign p_prev = paginator.previous_page_path
                       | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" href="{{ p_prev }}" 
           rel="prev">Previous</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">Previous</span>
      </li>
    {% endif %}

    <!-- Indicator Number. -->
    <li class="page-item disabled">
      <span class="page-link">
        Page: {{ paginator.page }} of {{ total_pages }}</span>
    </li>

    <!-- Next Page. -->
    {% if paginator.next_page %}
      {% assign p_next = paginator.next_page_path
                       | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" href="{{ p_next }}" 
           rel="next">Next</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">Next</span>
      </li>
    {% endif %}

    <!-- Last Page. -->
    {% unless paginator.page == total_pages %}
      {% assign p_last = site.paginate_path
                       | relative_url 
                       | replace: ':num', total_pages 
                       | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" href="{{ p_last }}" 
           rel="last">Last</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">Last</span>
      </li>
    {% endunless %}
  </ul>
  {% endif %}  
</nav>

Or alternatively with pagination-v2

Page Indicator

As simple as:

    <!-- Indicator Number. -->
    <li class="page-item disabled">
      <span class="page-link">
        Page: {{ paginator.page }} of {{ total_pages }}</span>
    </li>

2: Number

This preview is what we want to achieve:

Jekyll Bootstrap Pagination: 02 Number

HTML Preview

The HTML that we want to achieve in this article, is similar as below.

<nav aria-label="Page navigation">
  <ul class="pagination justify-content-center">

    <!-- Previous Page. -->
      <li class="page-item blog_previous">
        <a class="page-link" href="/pages/blog-4" rel="prev">&laquo;</a>
      </li>

    <!-- Page numbers. -->
      <li class="page-item ">
        <a href="/pages" class="page-link">1</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-2" class="page-link">2</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-3" class="page-link">3</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-4" class="page-link">4</a>
      </li>
      <li class="page-item  active">
        <span class="page-link">5</span>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-6" class="page-link">6</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-7" class="page-link">7</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-8" class="page-link">8</a>
      </li>
      <li class="page-item ">
        <a href="/pages/blog-9" class="page-link">9</a>
      </li>

    <!-- Next Page. -->
      <li class="page-item blog_next">
        <a class="page-link" href="/pages/blog-6" rel="next">&raquo;</a>
      </li>

  </ul>  
</nav>

Partial Liquid

We will achieve this with liquid code below:

{% capture spaceless %}
  {% if page.paginate_root == nil %}
    {% assign paginate_root = "/" %}
  {% else %}    
    {% assign paginate_root = page.paginate_root %}
  {% endif %}

  {% assign total_pages = paginator.total_pages %}
  {% assign color_main  = page.color_main  | default: layout.color_main %}
{% endcapture %}

<nav aria-label="Page navigation">
  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center">
    {% capture spaceless %}
      {% assign p_first = paginate_root
                        | prepend: site.baseurl %}
      {% assign page_current = paginator.page %}
    {% endcapture %}

    <!-- Previous Page. -->
    {% if paginator.previous_page %}
      {% assign p_prev = paginator.previous_page_path
                       | prepend: site.baseurl %}
      <li class="page-item blog_previous">
        <a class="page-link" href="{{ p_prev }}" rel="prev">&laquo;</a>
      </li>
    {% else %}
      <li class="page-item blog_previous disabled">
        <span class="page-link">&laquo;</span>
      </li>
    {% endif %}

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}
      <li class="page-item {% if page_cursor == page_current %} active{% endif %}">
      {% if page_cursor == page_current %}
        <span class="page-link">
          {{ page_cursor }}
        </span>
      {% else %}

        {% if page_cursor == 1 %}
          {% assign p_link = p_first %}
        {% else %}
          {% assign p_link = site.paginate_path
                           | relative_url
                           | replace: ':num', page_cursor 
                           | prepend: site.baseurl %}
        {% endif %}

        <a href="{{ p_link }}" class="page-link">
          {{ page_cursor }}
        </a>
       {% endif %}
      </li>
    {% endfor %}

    <!-- Next Page. -->
    {% if paginator.next_page %}
      {% assign p_next = paginator.next_page_path
                       | prepend: site.baseurl %}
      <li class="page-item blog_next">
        <a class="page-link" href="{{ p_next }}" rel="next">&raquo;</a>
      </li>
    {% else %}
      <li class="page-item blog_next disabled">
        <span class="page-link">&raquo;</span>
      </li>
    {% endif %}

  </ul>
  {% endif %}
</nav>

Or alternatively with pagination-v2

Loop: Page Number

As complex as:

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}
      <li class="page-item {% if page_cursor == page_current %} active{% endif %}">
      {% if page_cursor == page_current %}
        <span class="page-link">
          {{ page_cursor }}
        </span>
      {% else %}

        {% if page_cursor == 1 %}
          {% assign p_link = p_first %}
        {% else %}
          {% assign p_link = site.paginate_path
                           | relative_url
                           | replace: ':num', page_cursor 
                           | prepend: site.baseurl %}
        {% endif %}

        <a href="{{ p_link }}" class="page-link">
          {{ page_cursor }}
        </a>
       {% endif %}
      </li>
    {% endfor %}

This would be far shorter with custom plugin.

Explanation


3: Adjacent

Preview: General

It is not easy to explain by words. Let me explain what we want to achive by using these images below. The box without underline, is the active page. since we have 17 articles and 3 page for each pagination, then we have 9 pages of pagination. We have from first page (1), to last page (9).

This is what we want to achieve in this tutorial.

Jekyll Bootstrap Pagination: 03 Adjacent

Animation: Combined Version

This is the complete version. We will achieve this later.

Jekyll Pagination: Combined Animation

Animation: Stripped Version

I’m following Glenn McComb code, combined with my own code, and this is the result.

Jekyll Pagination: Adjacent Animation

HTML Preview

Just like previous, but filtered to show only number within link offset.

Partial Liquid: Variable Initialization

{% capture spaceless %}
  {% assign total_pages = paginator.total_pages %}
  {% assign color_main  = page.color_main  | default: layout.color_main %}
{% endcapture %}

  {% if total_pages > 1 %}
    {% capture spaceless %}
      <!-- Get paginate_root from page in frontmatter -->
      {% assign paginate_root = page.paginate_root %}
      {% assign p_first = paginate_root | prepend: site.baseurl %}

      {% assign page_current  = paginator.page %}

      {% assign link_offset   = 2 %}  
      {% assign link_max      = link_offset  | times: 2 | plus: 1 %}

      {% assign limit_lower   = link_offset  | plus: 1 %}
      {% assign limit_upper   = total_pages  | minus: link_offset %}
  
      {% assign min_lower     = link_max %}  
      {% assign max_upper     = total_pages  | minus: link_max %}
    
      {% assign lower_offset  = page_current | minus: link_offset %}  
      {% assign upper_offset  = page_current | plus: link_offset %}  
    {% endcapture %}
  {% endif %}

The link offset calculation is as below:

  {% if total_pages > 1 %}
  
    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}

      {% capture spaceless %}
        <!-- Flag Calculation -->
        {% assign page_current_flag = false %}

        {% if total_pages > link_max %}
        <!-- Complex page_cursor numbers. -->

          <!-- Lower limit pages. -->
          <!-- If the user is on a page_cursor which is in the lower limit.  -->
          {% if page_current <= limit_lower %}
            <!-- If the current loop page_cursor is less than max_links. -->
            {% if page_cursor <= min_lower %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Upper limit pages. -->
          <!-- If the user is on a page_cursor which is in the upper limit. -->
          {% elsif page_current >= limit_upper %}
            <!-- If the current loop page_cursor is greater than total pages minus $max_links -->
            {% if page_cursor > max_upper %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Middle pages. -->
          {% else %}
          
            {% if (page_cursor >= lower_offset) and (page_cursor <= upper_offset) %}
              {% assign page_current_flag = true %}
            {% endif %}

          {% endif %}

        {% else %}
        <!-- Simple page_cursor numbers. -->

          {% assign page_current_flag = true %}
        {% endif %}
      {% endcapture %}

      <!-- Show Pager. -->
      {% if page_current_flag == true %}
      ...
      {% endif %}

    {% endfor %}

  {% endif %}

This can be simplified using custom plugin.

Partial Liquid: HTML View

The complete view with liquid code is as below:

<nav aria-label="Page navigation">

  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center">
  
    {% capture spaceless %}
      <!-- Variable Initialization -->
      ...
    {% endcapture %}

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}

      {% capture spaceless %}
        <!-- Flag Calculation -->
        ...
      {% endcapture %}

      <!-- Show Pager. -->
      {% if page_current_flag == true %}
      <li class="page-item {% if page_cursor == page_current %} active{% endif %}">
        {% if page_cursor == page_current %} 
          <span class="page-link">
            {{ page_cursor }}
          </span>
        {% else %}

          {% capture spaceless %}
          {% if page_cursor == 1 %}
            {% assign p_link = p_first %}
          {% else %}
            {% assign p_link = site.paginate_path
                             | relative_url
                             | replace: ':num', page_cursor %}
            {% assign p_link = p_link 
                             | prepend: site.baseurl %}
          {% endif %}
          {% endcapture %}

          <a class="page-link"
             href="{{ p_link }}"
           >{{ page_cursor }}</a>
        {% endif %}
      </li>
      {% endif %}

    {% endfor %}

  </ul>
  {% endif %}
</nav>

Or alternatively the complete code with pagination-v2:

Explanation


4: Indicator

This preview is what we want to achieve:

Jekyll Bootstrap Pagination: 04 Indicator

You may add the word previous or next as code below. I just want to simplied the preview.

HTML Preview

<nav aria-label="Page navigation">
  <ul class="pagination justify-content-center">

    <!-- Previous Page. -->
      <li class="page-item">
        <a class="page-link" href="/pages/blog-4"
           rel="prev">&laquo;&nbsp;previous</a>
      </li>

      <!-- First Page. -->
        <li class="page-item first">
          <a class="page-link" href="/pages">1</a>
        </li>

      <!-- Early (More Pages) Indicator. -->
        <li class="pages-indicator first disabled">
          <span class="page-link">&hellip;</span>
        </li>

    <!-- Page numbers. -->
      <!-- Show Pager. -->
      <li class="page-item">
          <a class="page-link" href="/pages/blog-3">3</a>
      </li>
      <!-- Show Pager. -->
      <li class="page-item">
          <a class="page-link" href="/pages/blog-4">4</a>
      </li>
      <!-- Show Pager. -->
      <li class="page-item active">
          <span class="page-link">5</span>
      </li>

      <!-- Show Pager. -->
      <li class="page-item">
          <a class="page-link" href="/pages/blog-6">6</a>
      </li>

      <!-- Show Pager. -->
      <li class="page-item">
          <a class="page-link" href="/pages/blog-7">7</a>
      </li>

      <!-- Late (More Pages) Indicator. -->
        <li class="pages-indicator last disabled">
          <span class="page-link">&hellip;</span>
        </li>

      <!-- Last Page. -->
        <li class="page-item last">
          <a class="page-link" href="/pages/blog-9">9</a>
        </li>

    <!-- Next Page. -->
      <li class="page-item">
        <a class="page-link" href="/pages/blog-6" 
           rel="next">next&nbsp;&raquo;</a>
      </li>

  </ul>
</nav>

Small Animated Preview

This is the complete version.

Jekyll Pagination: Combined Animation

Partial Liquid

We will achieve this with liquid code below:

{% capture spaceless %}
  {% assign total_pages = paginator.total_pages %}
  {% assign color_main  = page.color_main  | default: layout.color_main %}
{% endcapture %}

<nav aria-label="Page navigation">

  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center">
  
    {% capture spaceless %}
      <!--
        Pagination links 
        * https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/
      -->

      <!-- Get paginate_root from page in frontmatter -->
      {% assign paginate_root = page.paginate_root %}
      {% assign p_first = paginate_root 
                        | prepend: site.baseurl %}
      {% assign p_last  = site.paginate_path
                        | relative_url 
                        | replace: ':num', total_pages %}

      {% assign page_current  = paginator.page %}

      {% assign link_offset   = 2 %}  
      {% assign link_max      = link_offset   | times: 2 | plus: 1 %}

      {% assign limit_lower   = link_offset   | plus: 1 %}
      {% assign limit_upper   = total_pages   | minus: link_offset %}
  
      {% assign min_lower     = link_max %}  
      {% assign max_upper     = total_pages   | minus: link_max %}
    
      {% assign lower_offset  = page_current  | minus: link_offset %}  
      {% assign upper_offset  = page_current  | plus: link_offset %}  

      {% assign lower_indicator = 2 %}
      {% assign upper_indicator = total_pages | minus: 1 %}

    {% endcapture %}

    <!-- Previous Page. -->
    {% if paginator.previous_page %}
      {% assign p_prev = paginator.previous_page_path
                       | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" 
           href="{{ p_prev }}"
           rel="prev">&laquo;&nbsp;previous</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">&laquo;&nbsp;previous</span>
      </li>
    {% endif %}

    {% if total_pages > link_max %}
      <!-- First Page. -->
      {% if lower_offset > 1 %}
        <li class="page-item first">
          <a class="page-link"
             href="{{ p_first }}">1</a>
        </li>
      {% endif %}

      <!-- Early (More Pages) Indicator. -->
      {% if lower_offset > lower_indicator %}
        <li class="pages-indicator first disabled">
          <span class="page-link">&hellip;</span>
        </li>
      {% endif %}
    {% endif %}

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}

      {% capture spaceless %}
        <!-- Flag Calculation -->
        {% assign page_current_flag = false %}

        {% if total_pages > link_max %}
        <!-- Complex page_cursor numbers. -->

          <!-- Lower limit pages. -->
          <!-- If the user is on a page_cursor which is in the lower limit.  -->
          {% if page_current <= limit_lower %}
            <!-- If the current loop page_cursor is less than max_links. -->
            {% if page_cursor <= min_lower %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Upper limit pages. -->
          <!-- If the user is on a page_cursor which is in the upper limit. -->
          {% elsif page_current >= limit_upper %}
            <!-- If the current loop page_cursor is greater than total pages minus $max_links -->
            {% if page_cursor > max_upper %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Middle pages. -->
          {% else %}
          
            {% if (page_cursor >= lower_offset) and (page_cursor <= upper_offset) %}
              {% assign page_current_flag = true %}
            {% endif %}

          {% endif %}

        {% else %}
        <!-- Simple page_cursor numbers. -->

          {% assign page_current_flag = true %}
        {% endif %}
      {% endcapture %}

      <!-- Show Pager. -->
      {% if page_current_flag == true %}
      <li class="page-item {% if page_cursor == page_current %} active{% endif %}">
        {% if page_cursor == page_current %} 
          <span class="page-link">
            {{ page_cursor }}
          </span>
        {% else %}

          {% capture spaceless %}
          {% if page_cursor == 1 %}
            {% assign p_link = p_first %}
          {% else %}
            {% assign p_link = site.paginate_path
                             | relative_url
                             | replace: ':num', page_cursor %}
            {% assign p_link = p_link 
                             | prepend: site.baseurl %}
          {% endif %}
          {% endcapture %}

          <a class="page-link"
             href="{{ p_link }}"
           >{{ page_cursor }}</a>
        {% endif %}
      </li>
      {% endif %}

    {% endfor %}

    {% if total_pages > link_max %}
      <!-- Late (More Pages) Indicator. -->
      {% if upper_offset < upper_indicator %}
        <li class="pages-indicator last disabled">
          <span class="page-link">&hellip;</span>
        </li>
      {% endif %}

      <!-- Last Page. -->
      {% if upper_offset < total_pages %}
        <li class="page-item last">
          <a class="page-link" 
             href="{{ p_last }}"
          >{{ total_pages }}</a>
        </li>
      {% endif %}
    {% endif %}

    <!-- Next Page. -->
    {% if paginator.next_page %}
      {% assign p_next = paginator.next_page_path
                       | prepend: site.baseurl %}
      <li class="page-item">
        <a class="page-link" 
           href="{{ p_next }}" 
           rel="next">next&nbsp;&raquo;</a>
      </li>
    {% else %}
      <li class="page-item disabled">
        <span class="page-link">next&nbsp;&raquo;</span>
      </li>
    {% endif %}

  </ul>
  {% endif %}
</nav>

Or alternatively with pagination-v2

Explanation


What is Next?

Consider continue reading [ Jekyll Bootstrap - Pagination - Responsive ].

Thank you for reading.