ssg  
Where to Discuss?

Local Group

Preface

Goal: Bringing responsive pagination, using mobile first.

Source Code

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


1: Source

Original Source

I respect copyright. The code below inspired by:

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

Of course, this article is talking about SASS

Altered Source

Coder will feel like home

While writing this CSS code, I can’t claim myself as a developer. Because CSS is not a programming language.

But weird that, responsive design has their own logic. So yeah, I have to code, a little.


2: Prepare

This step is required.

Preview: General

This is what we want to achieve in this tutorial.

11ty Pagination: Responsive Pagination

Layout: Nunjucks Blog

Consider use pagination/05-responsive partial, in blog.njk.

  {% include "pagination/05-responsive.njk" %}

SASS: Main

...

// Tailor Made
@import "main/layout-page"
@import "main/layout-content"
@import "main/decoration"
@import "main/pagination"
@import "main/list"

@import "post/content"
@import "post/navigation"

3: Navigation: HTML Class

The Final Result.

Consider have a look at the image below.

11ty Pagination: Responsive 2

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

<nav class="pagination is-small is-centered" ...>

    <ul class="pagination-list">
      <!-- Previous Page. -->
      <li class="blog-previous"><a class="pagination-previous" ...
        ><span class="fas fa-step-backward"></span>&nbsp;</a></li>

      <!-- First Page. -->
      <li class="first"><a class="pagination-link" ...>1</a></li>

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

      <!-- Page numbers. -->
      <li class="pagination--offset-2"><a class="pagination-link" ...>3</a></li>
      <li class="pagination--offset-1"><a class="pagination-link" ...>4</a></li>
      <li class="pagination--offset-0"><a class="pagination-link is-current" ...>5</a></li>
      <li class="pagination--offset-1"><a class="pagination-link" ...>6</a></li>
      <li class="pagination--offset-2"><a class="pagination-link" ...>7</a></li>

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

      <!-- Last Page. -->
      <li class="last"><a class="pagination-link" ...>9</a></li>

      <!-- Next Page. -->
      <li class="blog-next"><a class="pagination-next" ...
        >&nbsp;<span class="fas fa-step-forward"></span></a></li>
    </ul>

</nav>

11ty Pagination: Responsive Animation

Middle Pagination

All you need to care is, only these lines.

  <!-- Page numbers. -->
  <li class="pagination--offset-2">...</li>
  <li class="pagination--offset-1">...</li>
  <li class="pagination--offset-0">...</li>
  <li class="pagination--offset-1">...</li>
  <li class="pagination--offset-2">...</li>

Our short term goal is, to put the pagination--offsetclass.

Partial: Responsive Skeleton

As usual, the skeleton, to show the complexity.

{% if totalPages > 1 %}
<nav class="pagination is-small is-centered" ...>
  <ul class="pagination-list">

      <!-- First Page (arrow). -->
      <!-- Previous Page (arrow). -->

    {% if (totalPages > maxLinks) %}
      <!-- First Page (number = 1). -->
      <!-- Early (More Pages) Indicator. -->
    {% endif %}

    <!-- Page numbers. -->
    {% for cursor, link in pagination.links | hashIt %}
      ...
    {% endfor %}

    {% if (totalPages > maxLinks) %}
      <!-- Late (More Pages) Indicator. -->
      <!-- Last Page (number = total page). -->
    {% endif %}

      <!-- Next Page (arrow). -->
      <!-- Last Page (arrow). -->
  </ul>
</nav>
{% endif %}

Calculate Offset Value

Notice this part:

        <!-- Calculate Offset Class. -->
        {% set offset = (cursor - current) | abs %}
        {% set pageOffsetClass = 'pagination--offset-' + offset %}

Notice the new variable called pageOffsetClass.

Using Offset Class

All we need is just adding the offset class.

      <li class="{{ pageOffsetClass }}">
        ...
      </li>

Combined Code

      <!-- Show Pager. -->
      {% if showCursorFlag %}
        <!-- Calculate Offset Class. -->
        {% set offset = (cursor - current) | abs %}
        {% set pageOffsetClass = 'pagination--offset-' + offset %}

      <li class="{{ pageOffsetClass }}">
        {% if cursor == current  %}

        <a class="pagination-link is-current {{ color }}"
           aria-label="Page {{ cursor }}">
          {{ cursor }}
        </a>

        {% else %}

        <a class="pagination-link hoverable"
           href="{{ link }}"
           aria-label="Goto page {{ cursor }}">
          {{ cursor }}
        </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:

11ty Pagination: Responsive 1

11ty Pagination: Responsive 2

11ty Pagination: Responsive 3

11ty Pagination: Responsive 4

11ty Pagination: Responsive 5

SASS: Bulma Custom Breakpoint Variables.

I’m using custom breakpoint, instead of Bulma 7.x breakpoints.

// Breakpoint

$xs1: 0
$xs2: 320px
$xs3: 380px
$xs4: 480px
$sm1: 576px
$sm2: 600px
$md:  768px
$lg:  992px
$xl:  1200px

The name inspired by Bootsrap, but it has nothing do with Bootstrap.

SASS: Bulma Breakpoint Skeleton

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

ul.pagination-list
  +from($xs1)
  +from($xs2)
  +from($xs3)
  +from($xs4)
  +from($sm1)
  +from($sm2)
  +from($md)
  +from($lg)
  +from($xl)

SASS: Using Bulma Breakpoint: Simple

We can fill any rules, as below:

+tablet
  li.icon-previous a:after
    content: " Previous"
  li.icon-next a:before
    content: "Next "
  li.icon-first a:after
    content: " First"
  li.icon-last a:before
    content: "Last "
  li.icon-previous a span.fas,
  li.icon-next a span.fas,
  li.icon-first a span.fas,
  li.icon-last a span.fas
    display: none

SASS: Using Custom Breakpoint: Pagination Offset

We can fill any rules, inside pagination-list class as below: Such as pagination--offset setting, for each custom breakpoints.

// Responsiveness

ul.pagination-list
  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
  +from($xs1)
  +from($xs2)
  +from($xs3)
    li.pagination--offset-1
      display: inline-block
  +from($xs4)
    li.pagination--offset-2
      display: inline-block
  +from($sm1)
    li.icon-first,
    li.icon-last,
    li.pagination--offset-3
      display: inline-block
  +from($sm2)
    li.pagination--offset-4
      display: inline-block
  +from($md)
    li.pagination--offset-5,
    li.pagination--offset-6
      display: inline-block
  +from($lg)
    li.pagination--offset-7
      display: inline-block
  +from($xl)

This setup breakpoint is actually up to you. You may change to suit whatever you need.

SASS: Responsive Indicator

You can also add CSS rules for indicator, and stuff.

// Responsiveness

ul.pagination-list
  li.icon-first,
  li.icon-last,
  li.pages-indicator
    display: none
  +from($xs1)
  +from($xs2)
    li.pages-indicator
      display: inline-block
  +from($sm1)
    li.icon-first,
    li.icon-last,

Short and simple.

SASS: Decoration

If you desire, a slight enhancement without breaking the original looks.

Hover is a good idea.

// hover color

ul.pagination-list li 
  a:hover
    background-color: map-get($yellow, 'lighten-2')
    color: #000
  a.is-current:hover
    background-color: map-get($grey, 'base') !important
    color: #fff

And so is gap margin.

// layout

nav.pagination
  margin-top: 10px
  margin-bottom: 10px

SASS: Complete Code

Now you can have the complete code as below:

+tablet
  li.icon-previous a:after
    content: " Previous"
  li.icon-next a:before
    content: "Next "
  li.icon-first a:after
    content: " First"
  li.icon-last a:before
    content: "Last "
  li.icon-previous a span.fas,
  li.icon-next a span.fas,
  li.icon-first a span.fas,
  li.icon-last a span.fas
    display: none

// Breakpoint

$xs1: 0
$xs2: 320px
$xs3: 380px
$xs4: 480px
$sm1: 576px
$sm2: 600px
$md:  768px
$lg:  992px
$xl:  1200px

// Responsiveness

ul.pagination-list
  li.icon-first,
  li.icon-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
  +from($xs1)
  +from($xs2)
    li.pages-indicator
      display: inline-block
  +from($xs3)
    li.pagination--offset-1
      display: inline-block
  +from($xs4)
    li.pagination--offset-2
      display: inline-block
  +from($sm1)
    li.icon-first,
    li.icon-last,
    li.pagination--offset-3
      display: inline-block
  +from($sm2)
    li.pagination--offset-4
      display: inline-block
  +from($md)
    li.pagination--offset-5,
    li.pagination--offset-6
      display: inline-block
  +from($lg)
    li.pagination--offset-7
      display: inline-block
  +from($xl)

// hover color

ul.pagination-list li 
  a:hover
    background-color: map-get($yellow, 'lighten-2')
    color: #000
  a.is-current:hover
    background-color: map-get($grey, 'base') !important
    color: #fff

// layout

nav.pagination
  margin-top: 10px
  margin-bottom: 10px

5: Summary

You can have a look at our complete code here:

{% set totalPages = pagination.links.length %}
{% set current    = pagination.pageNumber + 1 %}

{# 
* Pagination links 
* https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/
* Adjacent: Number of links either side of the current page
#}

{% if totalPages > 1 %}
<nav class="pagination is-small is-centered"
     role="navigation" aria-label="pagination">

  {% set adjacentLinks = 2 %}
  {% set maxLinks      = (adjacentLinks * 2) + 1 %}

  <ul class="pagination-list">

      <!-- First Page. -->
      <li class="icon-first">
      {% if current > 1 %}
        <a class="pagination-previous hoverable"
           href="{{ pagination.firstPageLink }}"
           rel="first">
          <span class="fas fa-step-backward"></span>&nbsp;</a>
      {% else %}
        <a class="pagination-previous"
           title="This is the first page"
           disabled>
          <span class="fas fa-step-backward"></span>&nbsp;</a>
      {% endif %}
      </li>

      <!-- Previous Page. -->
      <li class="icon-previous">
      {% if pagination.previousPageLink %}
        <a class="pagination-previous hoverable"
           href="{{ pagination.previousPageLink }}"
           rel="prev">
          <span class="fas fa-backward"></span>&nbsp;</a>
      {% else %}
        <a class="pagination-previous"
           title="This is the first page"
           disabled>
          <span class="fas fa-backward"></span>&nbsp;</a>
      {% endif %}
      </li>

    {% if (totalPages > maxLinks) %}
      <!-- First Page. -->
      {% if (current - adjacentLinks > 1) %}
      <li>
        <a class="pagination-link hoverable"
           href="{{ pagination.firstPageLink }}"
           aria-label="Goto page 1">1</a>
      </li>
      {% endif %}

      <!-- Early (More Pages) Indicator. -->
      {% if (current - adjacentLinks > 2) %}
      <li class="pages-indicator">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {% endif %}
    {% endif %}

    <!-- Page numbers. -->
    {% for cursor, link in pagination.links | hashIt %}

      <!-- Adjacent script based on Glenn Mc Comb. -->
      {% set showCursorFlag = cursor | 
               isShowAdjacent(current, totalPages, adjacentLinks) %}

      <!-- Show Pager. -->
      {% if showCursorFlag %}
        <!-- Calculate Offset Class. -->
        {% set offset = (cursor - current) | abs %}
        {% set pageOffsetClass = 'pagination--offset-' + offset %}

      <li class="{{ pageOffsetClass }}">
        {% if cursor == current  %}

        <a class="pagination-link is-current {{ color }}"
           aria-label="Page {{ cursor }}">
          {{ cursor }}
        </a>

        {% else %}

        <a class="pagination-link hoverable"
           href="{{ link }}"
           aria-label="Goto page {{ cursor }}">
          {{ cursor }}
        </a>

        {% endif %}
      </li>
      {% endif %}

    {% endfor %}

    {% if (totalPages > maxLinks) %}
      <!-- Late (More Pages) Indicator. -->
      {% if (current + adjacentLinks < totalPages - 1)  %}
      <li class="pages-indicator">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {% endif %}

      <!-- Last Page. -->
      {% if (current + adjacentLinks < totalPages) %}
      <li>
        <a class="pagination-link hoverable" 
           href="{{ pagination.lastPageLink }}"
           aria-label="Goto page {{ totalPages }}">
          {{ totalPages }}</a>
      </li>
      {% endif %}
    {% endif %}

      <!-- Next Page. -->
      <li class="icon-next">
      {% if pagination.nextPageLink %}
        <a class="pagination-next hoverable"
           href="{{ pagination.nextPageLink }}"
           rel="next">&nbsp;
          <span class="fas fa-forward"></span></a>
      {% else %}
        <a class="pagination-next"
           title="This is the last page"
           disabled>&nbsp;
          <span class="fas fa-forward"></span></a>
      {% endif %}
      </li>

      <!-- Last Page. -->
      <li class="icon-last">
      {% if current != totalPages %}
        <a class="pagination-next hoverable"
           href="{{ pagination.lastPageLink }}"
           rel="last">&nbsp;
          <span class="fas fa-step-forward"></span></a>
      {% else %}
        <a class="pagination-next"
           title="This is the last page"
           disabled>&nbsp;
          <span class="fas fa-step-forward"></span></a>
      {% endif %}
      </li>

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

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.

Browser: Pagination Preview

Finally the animated version.

11ty Pagination: Responsive Animation


What is Next ?

Consider continue reading [ Eleventy - Pagination - Screenreader ]. We are going to conclude pagination with screenreader.

Thank you for reading.