ssg  
Article Series

This article series contain few sections.


Obsolete Repository:
This article use obsolete repository. Please refer to below repository for a more recent articles.

Complete Repository

Where to Discuss?

Local Group

Preface

Goal: Bringing responsive pagination, using mobile first.

Preview

This is what we want to achieve in this tutorial.

Hugo Pagination: Responsive Animation

More Recent Code

I have made a better code with Bulma utilizing site.pagination.permalink which you can examine at:


1: Prepare

Artefact that we need. We should switch our focus, to stylesheet using SASS instead of Jekyll Liquid.

Source

I respect copyright. The SASS code below inspired by:

I made a slight modification. But of course the logic remain the same.

Includes: Pagination: Responsive

Create an empty artefact. Source code used in this tutorial, is available at this repository:

  • /_includes/pagination/05-responsive.html

You should have this minimal code, before you begin.

{% capture spaceless %}
  ...
{% endcapture %}

<nav aria-label="Page navigation">

  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center">

  ...

  </ul>
  {% endif %}

</nav>

Pages: Blog List

Set this blog list page:

  {% include pagination/05-responsive.html %}

SASS: Main

@import
  // variables
    "bootstrap/functions",
    "variables",
    "bootstrap/variables",
    "bootstrap/mixins/breakpoints",

  // taken from bootstrap
  // ...

  // custom: general
  // ...
    "pagination"
;

SASS: Custom Pagination

I’m using Bootstrap 4 grid breakpoints.

@include media-breakpoint-up(md) {
  ...
}

2: Navigation: HTML Class

The Final Result.

Consider have a look at the image below.

Hugo Pagination: Responsive 1

The HTML that we want to achieve is similar as below.

  <ul class="pagination justify-content-center">
      <li class="page-item blog_previous">...</li>
      <li class="page-item first">...</li>
      <li class="pages-indicator first disabled">...</li>
      <li class="page-item pagination--offset-2">...</li>
      <li class="page-item pagination--offset-1">...</li>
      <li class="page-item pagination--offset-0 active ">...</li>
      <li class="page-item pagination--offset-1">...</li>
      <li class="page-item pagination--offset-2">...</li>
      <li class="pages-indicator last disabled">...</li>
      <li class="page-item last">...</li>
      <li class="page-item blog_next">...</li>
  </ul>

Middle Pagination

All you need to care is, only these lines.

      <li class="page-item pagination--offset-2">...</li>
      <li class="page-item pagination--offset-1">...</li>
      <li class="page-item pagination--offset-0 active ">...</li>
      <li class="page-item pagination--offset-1">...</li>
      <li class="page-item pagination--offset-2">...</li>

Our short term goal is, to put the pagination–offset class.

Partial: Pagination Code Skeleton

As usual, the skeleton, to show the complexity.

<nav aria-label="Page navigation">
{% capture spaceless %}
  <!-- Variable Initialization. -->
{% endcapture %}

  {% if total_pages > 1 %}
  <ul class="pagination justify-content-center">

    <!-- Previous Page. -->
    <!-- First Page. -->
    <!-- Early (More Pages) Indicator. -->

    {% for page in (1..total_pages) %}
      <!-- Flag Calculation -->
      {% assign page_current_flag = false %}

      {% if total_pages > link_max %}
        <!-- Complex page numbers. -->
      
          <!-- Lower limit pages. -->
          <!-- Upper limit pages. -->
          <!-- Middle pages. -->

      {% else %}
        <!-- Simple page numbers. -->
      {% endif %}

      {% if page_current_flag == true %}
      <!-- Calculate Offset Class. -->
      {% endif %}

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

    <!-- Late (More Pages) Indicator. -->
    <!-- Last Page. -->
    <!-- Next Page. -->

  </ul>
  {% endif %}

</nav>

Notice this new section

  • Calculate Offset Class.

Partial: Pagination Code: Long Version

Before you begin, consider copy-and-paste from our last tutorial.

Calculate Offset Value

It is just a matter of difference, between current page and pager.

      {% if page_current_flag == true %}
      <!-- Calculate Offset Class. -->
        {% assign diff_offset = page | minus: page_current | abs %}
      {% endif %}

We are lucky that, Jekyll Liquid have this abs.

Using Offset Class

All we need is just adding the offset class.

      <li class="page-item pagination--offset-{{ diff_offset }}">
        ...
      </li>

Combined Code

The real code, is also not very simple.

    {% capture spaceless %}
      {% if page_current_flag == true %}
      <!-- Calculate Offset Class. -->
        {% assign diff_offset = page | minus: page_current | abs %}
      {% endif %}
    {% endcapture %}

      <!-- Show Pager. -->
      {% if page_current_flag == true %}
      <li class="page-item {% if page == page_current %} active{% endif %} pagination--offset-{{ diff_offset }}">
        {% if page == page_current %} 
          <span class="page-link">
            {{ page }}
          </span>
        {% elsif page == 1 %}
          <a class="page-link"
             href="{{ site.baseurl }}{{ paginate_root }}"
           >1</a>
        {% else %}
          <a class="page-link"
             href="{{ site.paginate_path | relative_url | replace: ':num', page }}"
           >{{ page }}
          </a>
        {% endif %}
      </li>
      {% endif %}

That is all. Now that the HTML part is ready, we should go on, by setting up the responsive breakpoints using SCSS.


4: Responsive: Breakpoints

Responsive is easy if you understand the logic.

It is all about breakpoints.

Preview: Each Breakpoint

Consider again, have a look at the animation above, frame by frame. We have at least five breakpoint as six figures below:

Hugo Pagination: Responsive 1

Hugo Pagination: Responsive 2

Hugo Pagination: Responsive 3

Hugo Pagination: Responsive 4

Hugo Pagination: Responsive 5

Hugo Pagination: Responsive 6

SASS: Bootstrap Grid Breakpoint Variables.

Bootstrap 4 grid breakpoints are defined as below.

  • _sass/vendors/bootstrap/_variables.scss
// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.

$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
) !default;

SASS: Bootstrap Breakpoint Skeleton

With breakpoint above, we can setup css skeleton, with empty css rules.

ul.pagination {
  @include media-breakpoint-up(xs) {}  
  @include media-breakpoint-up(sm) {}
  @include media-breakpoint-up(md) {}
  @include media-breakpoint-up(lg) {}
  @include media-breakpoint-up(xl) {}
}

SASS: Using Bootstrap Breakpoint: Simple

We can fill any rules, as below:

@include media-breakpoint-up(md) {

  .blog_previous {
    span.page-link:after,
    a.page-link:after {
      content: " previous"
    }
  }

  .blog_next {
    span.page-link:before,
    a.page-link:before {
      content: "next "
    }
  }

}

SASS: Using Bootstrap Breakpoint: Pagination Offset

We can fill any rules, inside pagination class as below:

ul.pagination {

  li.pagination--offset-1,
  li.pagination--offset-2,
  li.pagination--offset-3,
  li.pagination--offset-4,
  li.pagination--offset-5,
  li.pagination--offset-6,
  li.pagination--offset-7 {
    display: none;
  }

  @include media-breakpoint-up(xs) {
  }
  
  @include media-breakpoint-up(sm) {
    li.pagination--offset-1,
    li.pagination--offset-2 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(md) {
    li.pagination--offset-3,
    li.pagination--offset-4 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(lg) {
    li.pagination--offset-5,
    li.pagination--offset-6,
    li.pagination--offset-7 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(xl) {
  }

}

SASS: Responsive Indicator

You can also add CSS rules for indicator.

ul.pagination {

  li.first,
  li.last,
  li.pages-indicator {
    display: none;
  }

  @include media-breakpoint-up(xs) {
  }
  
  @include media-breakpoint-up(sm) {
    li.pages-indicator {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(md) {
    li.first,
    li.last {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(lg) {
  }

  @include media-breakpoint-up(xl) {
  }

}

SASS: Enhanced Bootstrap Breakpoint

If you desire smoother transition effect, you can create your own breakpoint, beyond bootstrap.

$grid-breakpoints-custom: (
  xs:  0,
  xs2: 320px,
  xs3: 400px,
  xs4: 480px,
  sm:  576px,
  sm2: 600px,
  md:  768px,
  lg:  992px,
  xl:  1200px
) !default;

And later, add css rule as code below:

ul.pagination {
  @include media-breakpoint-up(xs2, $grid-breakpoints-custom) {
    li.pages-indicator {
      display: inline-block;
    }
  }
}

SASS: Complete Code

Now you can have the complete code as below:

@include media-breakpoint-up(md) {

  .blog_previous {
    span.page-link:after,
    a.page-link:after {
      content: " previous"
    }
  }

  .blog_next {
    span.page-link:before,
    a.page-link:before {
      content: "next "
    }
  }

}

$grid-breakpoints-custom: (
  xs:  0,
  xs2: 320px,
  xs3: 400px,
  xs4: 480px,
  sm:  576px,
  sm2: 600px,
  md:  768px,
  lg:  992px,
  xl:  1200px
) !default;

ul.pagination {

  li.first,
  li.last,
  li.pages-indicator {
    display: none;
  }

  li.pagination--offset-1,
  li.pagination--offset-2,
  li.pagination--offset-3,
  li.pagination--offset-4,
  li.pagination--offset-5,
  li.pagination--offset-6,
  li.pagination--offset-7 {
    display: none;
  }

  @include media-breakpoint-up(xs, $grid-breakpoints-custom) {
  }
  
  @include media-breakpoint-up(xs2, $grid-breakpoints-custom) {
    li.pages-indicator {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(xs3, $grid-breakpoints-custom) {
    li.pagination--offset-1 {
      display: inline-block;
    }
  }
  
  @include media-breakpoint-up(xs4, $grid-breakpoints-custom) {
    li.pagination--offset-2 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(sm, $grid-breakpoints-custom) {
    li.first,
    li.last,
    li.pagination--offset-3 {
      display: inline-block;
    }
  }
  
  @include media-breakpoint-up(sm2, $grid-breakpoints-custom) {
    li.pagination--offset-4 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(md, $grid-breakpoints-custom) {
    li.pagination--offset-5,
    li.pagination--offset-6 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(lg, $grid-breakpoints-custom) {
    li.pagination--offset-7 {
      display: inline-block;
    }
  }

  @include media-breakpoint-up(xl, $grid-breakpoints-custom) {
  }

}

5: Summary

You can have a look at our complete code here:

We will have to complete the code later, in the next article. This has been a long article. We still need a few changes, for screen reader, and clean-up unneeded comments.


What is Next ?

Consider continue reading [ Jekyll Pagination - Screenreader ].

Thank you for reading.