ssg  
Where to Discuss?

Local Group

Preface

Goal: An introduction to pagination.

Pagination is a whole big topic, that takes about more than six articles. It is rare that common front end web based component require algorithm. This pagination takes thinking time, instead of just rely on design skill.

However, do not ever let this complex code intimidate you. In fact, pagination code in Eleventy is simpler than Hexo, simpler than Jekyll, and simpler than Hugo.

Source Code

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


1: Article Provided

For each step, I made different layout, and explain the deatil in separate articles. This article series start from simple pagination layout.

Step By Step

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

  • Layout 01: Simple

  • Layout 02: Number

  • Layout 03: Adjacent

  • Layout 04: Indicator

  • Layout 05: Responsive

  • Layout 06: Screen Reader

This is the spoiler, of what we are going to do in this article series.

Additional

I also provide other additional article as well:

  • Introduction

  • Navigation Style (using layout 02 as example)

Preview

Responsive

11ty Pagination: Responsive Animation

Alternate Pagination

11ty Pagination: Alternate Animation


2: Prepare: Page Content.

This preparation is required.

Filter: pagerIt

sorry for my english

I create my own filter to manage permalink, for nicer URL pagination.

  // First Page has no additional path.
  eleventyConfig.addNunjucksFilter("pagerIt", function(pageNumber) {
    var path = "page-"+(pageNumber+1)+"/index.html";

    if (pageNumber == 0 ) { path = "index.html"; }

    return path;
  });

With these filter you can have these urls, as below example:

  • Page 1: http://localhost:8080/pages/index.html

And consecutively

  • Page 2: http://localhost:8080/pages/page-2/index.html

  • Page 3: http://localhost:8080/pages/page-3/index.html

  • Page 4: http://localhost:8080/pages/page-4/index.html

11ty: Tree Build URL

You can use this filter later, in frontmatter below:

permalink : pages/{{ pagination.pageNumber | pagerIt }}

Filter: hashIt

The second filter is, shifting array number to human number. As you know array start from zero, while page number is page one, page two, page three, and so on.

  // First Page is 1: Retarded array in contrast with zero based.
  eleventyConfig.addNunjucksFilter("hashIt", function(array) {
    var hash = {};
    var i;
    for (i = 0; i < array.length; i++) {
      hash[i+1] = array[i];
    } 

    return hash;
  });

You can use this filter later, in loop below:

    {% for cursor, link in pagination.links | hashIt %}
      ...
    {% endfor %}

Page Content: Blog

Pagination in Eleventy is set up in content.

---
layout    : blog
title     : Blog List
eleventyExcludeFromCollections: true

pagination:
  data: collections.posts
  size: 2
  alias: posts

permalink : pages/{{ pagination.pageNumber | pagerIt }}

showPagination : true
---

{% include "index/blog-list.njk" %}

Since we have very few article, we set the pagination to 2. For real life blog, you can use 7 or 10 or else. It is all up to you.

Note that the frontmatter variable named showPagination is, a custom variable that I create. It is not from official eleventy pagination.

Content: Example Article

Just make sure you have enough article, to test all pagination case.

❯ tree views/lyrics views/quotes
views/lyrics
├── 5fdp-wash-it-all-the-way.md
├── deftones-be-quiet-and-drive.md
├── disturbed-stupify.md
├── eurythmics-sweet-dreams.md
├── house-of-pain-jump-around.md
├── marylin-manson-redeemer.md
├── onyx-slam.md
├── public-enemy-bring-the-noise.md
├── ratm-bulls-on-parade.md
├── soulfly-jump-da-fuck-up.md
├── soundgarden-black-hole-sun.md
└── white-zombie-more-human-than-human.md
views/quotes
├── dead-poets-society.md
├── every-day.md
├── fight-club.md
├── jerry-maguire.md
└── scott-pilgrim.md

0 directories, 17 files

Here we have 17 articles.

11ty: Tree Posts Content


3: Layout

Consider make a slight change in layout/blog.njk partial.

Partial: Pagination

Since pagination code can be complex, it is better to put, the pagination as partial, somewhere else.

{% block pagination %}  
  {% set color = color or 'brown' %}
  {% include "pagination/06-screenreader.njk" %}
{% endblock %}

All Pagination Options

Since we are going to have six steps, we may switch the layout often, so we need a way to copy-and-paste easily. Here below an unused block that contain each pagination step. You should only select one of them.

{% block pagination_all %}  
  {% include "pagination/01-simple.njk" %}
  {% include "pagination/02-number.njk" %}
  {% include "pagination/03-adjacent.njk" %}
  {% include "pagination/04-indicator.njk" %}
  {% include "pagination/05-responsive.njk" %}
  {% include "pagination/06-screenreader.njk" %}
{% endblock %}

Layout: Nunjucks Blog

The complete code is as below.

{% extends "layouts/column-single.njk" %}

{% block main_color %}{{ color or 'brown' }}{% endblock %}

{% block pagination %}  
  {% set color = color or 'brown' %}
  {% include "pagination/06-screenreader.njk" %}
{% endblock %}

{% block pagination_all %}  
  {% include "pagination/01-simple.njk" %}
  {% include "pagination/02-number.njk" %}
  {% include "pagination/03-adjacent.njk" %}
  {% include "pagination/04-indicator.njk" %}
  {% include "pagination/05-responsive.njk" %}
  {% include "pagination/06-screenreader.njk" %}
{% endblock %}

Parent Layout: Nunjucks Single Columns

I create my own frontmatter variable named showPagination, in parent layout for single column layout.

{% extends "layouts/base.njk" %}

{% block main %}
{%- set color %}{% block main_color %}blue{% endblock %}{% endset -%}

  <main role="main" 
        class="column is-full">
    <section class="main-wrapper {{ color }}">
      <div class="blog white z-depth-3 hoverable">
       ...

        {%- if showPagination -%}
        <section class="blog-index center-align" itemprop="pagination">
        {% block pagination %}{% endblock %}
        </section>
        {%- endif -%}

        ...
      </div>
    </section>
  </main>
{% endblock %}

From now on we will use pagination extensively.


4: Skeleton

This part is the most basic part, and would be used in each layout for each step.

Layout: Nunjucks Pagination Code

The skeleton is similar as below:

<!-- helper function -->
<!-- variable initialization -->
<nav class="pagination is-small is-centered" 
     role="navigation"
     aria-label="pagination">

    <ul class="pagination-list">
      <!-- left  navigation code -->
      <!-- middle numbering code -->
      <!-- right navigation code -->
    </ul>

</nav>

Navigation code contain buttons such as:

  • Left Pagination: First

  • Left Pagination: Previous

  • Right Pagination: Next

  • Right Pagination: Last

While numbering code is in the middle

  • Middle Pagination: Numbering

Notice that, you may easily change the position. For example, put the middle pagination on right side, instead of in the middle. So alternatively you can switch to:

<!-- helper function -->
<!-- variable initialization -->
<nav class="pagination is-small is-centered" 
     role="navigation"
     aria-label="pagination">

    <!-- navigation code -->

    <ul class="pagination-list">
      <!-- numbering code -->
    </ul>

</nav>

Minimal Logic

The pagination would only be shown, if there is more than one pagination page. No need to show any pagination navigation, if what we have is only one page. Hence our minimal pagination logic would be:

{% set totalPages = pagination.links.length %}

{% if totalPages > 1 %}
<nav ...>
    ...
    <!-- pagination code -->

</nav>
{% endif %}

Of course this is not enough. Our minimal pagination should show something.

Loop

The loop for each pagination, is simply as below:

    {% for cursor, link in pagination.links | hashIt %}
      ...
    {% endfor %}

I’m using the term cursor.


5: Math: Algebra

Assumption

Consider an example, this blog post that contain seventeen posts.

# CONST

Total Post   = 17
Per Page     = 2

# COMPUTED

totalPages   = 9

Equation

And change the number of page for each pagination, by number for example: 2, 3, 4, 5, 10, 20.

pagination:
  data: collections.posts
  size: 2
  alias: posts

Table

Do not worry! totalPages do the math internally in eleventy.

{% set totalPages = pagination.links.length %}

We can also achieve totalPages by ceiling division. And the result is on this table below.

# ALGEBRA

+-------------+-------+-------+-------+-------+-------+
| pagination  |   2   |   3   |   5   |  10   |  20   |
+-------------+-------+-------+-------+-------+-------+
| VARIABLE                                            |
| division    |  8.5  |  5.7  |  3.4  |  1.7  |  0.85 |
| totalPages  |   9   |   6   |   4   |   2   |  N/A  |
+-------------+-------+-------+-------+-------+-------+

Of course, we do not need to show any pagination, if there is only one page for all result. That is why we can optionally, convert 1 into N/A.


What is Next ?

Now we are ready to begin this pagination journey.

Consider continue reading [ Eleventy - Pagination - Simple ]. We should start from the simple one.

Thank you for reading.