Where to Discuss?

Local Group

Preface

Goal: Step by step demo of custom pagination using Bulma

I have already made an article about Bootstrap pagination in Hugo. I do not want to talk about Bulma pagination in very detail fashioned. This would be a brief summary on how I built the pagination

Hugo Pagination: Indicator Animation

Hugo Pagination: Responsive Animation

Source Code

You can download the source code of this article here.

I also wrote about Hugo Bootstrap Pagination. Step by step article, that you can read here:


1: Prepare

Prepare this sitewide configuration.

Theme

Still with tutor-05.

theme        = "tutor-05"

Pagination Limit

Pagination can be set in config.toml

Paginate     = 7

SASS

We require this custom SASS

+tablet
  li.blog-previous a:after
    content: " previous"
  li.blog-next a:before
    content: "next "
...

2: Paginator

We will this paginator object throughout this long article. This paginator would stay in archives/list.html layout.

Paginator Filtering

In layout we are going to use

{{ $paginator := .Paginate .Site.Pages }}

Since we only show specific page kind named post, we should filter the pages using where.

{{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}

Layout: List

The complete file would be as follow:

{{ define "main" }}
<main role="main" 
      class="column is-full box-deco has-background-white">
  <header>
    <h4 class="title is-4">{{ .Title | default .Site.Title }}</h4>
  </header>

  <section class="section">
    {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
    {{ partial "pagination/01-simple.html" (dict "p" $paginator) }}
  </section>

  <div class="post-list">
  {{ range $paginator.Pages }}
    <section class="section" id="archive">
      {{ partial "summary/blog-list.html" . }}
    </section>
  {{ end }}
  </div>
{{ end }}
</main>

I also put the code for each process in the same file artefact. So you can easliy switch between one of the pagination.

{{ define "pagination-steps" }}
{{/*
  You may choose one of our pagination:

  {{ partial "pagination/01-simple.html" (dict "p" $paginator) }}
  {{ partial "pagination/02-number.html" (dict "p" $paginator) }}
  {{ partial "pagination/03-adjacent.html" (dict "p" $paginator "s" .Scratch) }}
  {{ partial "pagination/04-indicator.html" (dict "p" $paginator "s" .Scratch) }}
  {{ partial "pagination/05-responsive.html" (dict "p" $paginator "s" .Scratch) }}
  {{ partial "pagination/06-screenreader.html" (dict "p" $paginator "s" .Scratch) }}
*/}}
{{ end }}

Dictionary

In order to pass variable from list layout to pagination partial, we utilize dictionary: (dict “p” $paginator).

  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination-simple.html" (dict "p" $paginator) }}

Testing Pagination

While debugging, or development process, we can do this to override sitewide paginate configuration. Here we can use 5 articles for each pagination page.

{{ $paginator := .Paginate (where .Site.Pages "Type" "post") 5 }}

This is a very helpful trick for me.

Content

To make it easy to count, I’m going to use exactly ten pages, so we can have exactly ten pagination. We can achieve this using

{{ $paginator := .Paginate (where .Site.Pages "Type" "post") 1 }}

Make sure you have only ten content with post kind. Comment the type just in case you need.

+++
# type   = "post"
title  = "Everyday I Ask"
... 
+++

3: Simple

Goal: Pagination for dummies, a simple introduction.

This is what we want to achieve in this tutorial.

Hugo Pagination: Simple

We will achieve this with Hugo code.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/01-simple.html" (dict "p" $paginator) }}

Partial: Pagination Simple

Complete code is here below:

<nav class="pagination is-small is-centered" 
     role="navigation" aria-label="pagination">
  {{ if gt .p.TotalPages 1 }}
    <!-- First Page. -->
    {{ if not (eq .p.PageNumber 1) }}
      <a class="pagination-previous" href="{{ .p.First.URL }}" 
         rel="first">First</a>
    {{ else }}
      <a class="pagination-previous" title="This is the first page"
         disabled>First</a>
    {{ end }}

    <!-- Previous Page. -->
    {{ if .p.HasPrev }}
      <a class="pagination-previous" href="{{ .p.Prev.URL }}" 
         rel="prev">Previous</a>
    {{ else }}
      <a class="pagination-previous" title="This is the first page"
         disabled>Previous</a>
    {{ end }}

    <!-- Indicator Number. -->
    <a class="pagination-link" 
       disabled>Page: {{ .p.PageNumber }} of {{ .p.TotalPages }}</a>

    <!-- Next Page. -->
    {{ if .p.HasNext }}
      <a class="pagination-next" href="{{ .p.Next.URL }}" 
         rel="next">Next</a>
    {{ else }}
      <a class="pagination-next" title="This is the last page"
         disabled>Next</a>
    {{ end }}

    <!-- Last Page. -->
    {{ if not (eq .p.PageNumber .p.TotalPages) }}
      <a class="pagination-next" href="{{ .p.Last.URL }}" 
         rel="last">Last</a>
    {{ else }}
      <a class="pagination-next" title="This is the last page"
         disabled>Last</a>
    {{ end }}

    <!-- Dummy. Do not delete! -->
    <ul class="pagination-list">
    </ul>

  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

  • 480px screen wide

Hugo Pagination: Simple

  • 640px screen wide

Hugo Pagination: Simple

  • 800px screen wide

Hugo Pagination: Simple

How does it works ?

You can see the detail in bootstrap article.


4: Number

Goal: Pagination for dummies, list all of page.

This is what we want to achieve in this tutorial.

Hugo Pagination: Number

We will achieve this with Hugo code.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/02-number.html" (dict "p" $paginator) }}

Partial: Pagination Number

Complete code is here below:

<nav class="pagination is-small is-centered" 
     role="navigation" aria-label="pagination">
  {{ if gt .p.TotalPages 1 }}
    <!-- First Page. -->
    {{ if not (eq .p.PageNumber 1) }}
      <a class="pagination-previous" href="{{ .p.First.URL }}" 
         rel="first">First</a>
    {{ else }}
      <a class="pagination-previous" title="This is the first page"
         disabled>First</a>
    {{ end }}

    <!-- Previous Page. -->
    {{ if .p.HasPrev }}
      <a class="pagination-previous" href="{{ .p.Prev.URL }}" 
         rel="prev">Previous</a>
    {{ else }}
      <a class="pagination-previous" title="This is the first page"
         disabled>Previous</a>
    {{ end }}

    <!-- Next Page. -->
    {{ if .p.HasNext }}
      <a class="pagination-next" href="{{ .p.Next.URL }}" 
         rel="next">Next</a>
    {{ else }}
      <a class="pagination-next" title="This is the last page"
         disabled>Next</a>
    {{ end }}

    <!-- Last Page. -->
    {{ if not (eq .p.PageNumber .p.TotalPages) }}
      <a class="pagination-next" href="{{ .p.Last.URL }}" 
         rel="last">Last</a>
    {{ else }}
      <a class="pagination-next" title="This is the last page"
         disabled>Last</a>
    {{ end }}

    <ul class="pagination-list">
      <!-- Page numbers. -->
      {{ $pagenumber := .p.PageNumber }}

      {{ range .p.Pagers }}
      <li>
        {{ if not (eq $pagenumber .PageNumber) }} 
        <a href="{{ .URL }}" class="pagination-link" 
           aria-label="Goto page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ else }}
        <a class="pagination-link is-current" 
           aria-label="Page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ end }}
      </li>
      {{ end }}
    </ul>
  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

  • 480px screen wide

Hugo Pagination: Number

  • 640px screen wide

Hugo Pagination: Number

  • 800px screen wide

Hugo Pagination: Number

How does it works ?

You can see the detail in bootstrap article.


5: Adjacent

This is actually, an advance pagination. Not so for dummies.

Goal: Explaining Glenn McComb Pagination using Math and Table.

Source

I respect copyright. The code below copied, and pasted from:

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

I mostly write it down in my blog, because I do not want to forget what I learn. An easier place for me to find the modified version of this good code.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/03-adjacent.html" (dict "p" $paginator "s" .Scratch) }}

Partial: Pagination Adjacent

The code is complex, but interesting for coder. Complete code is here below:

{{/* 

Pagination links 
* https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/

*/}}
<nav class="pagination is-small is-centered"
     role="navigation" aria-label="pagination">
  {{ $s := .s }}
  {{ $p := .p }}

  {{ if gt .p.TotalPages 1 }}
    <ul class="pagination-list">

    <!-- Page numbers. -->
    {{- $pagenumber := $p.PageNumber -}}

    <!-- Number of links either side of the current page. -->
    {{ $adjacent_links := 2 }}

    <!-- $max_links = ($adjacent_links * 2) + 1 -->
    {{ $max_links := (add (mul $adjacent_links 2) 1) }}

    <!-- $lower_limit = 1 + $adjacent_links -->
    {{ $lower_limit := (add 1 $adjacent_links) }}

    <!-- $upper_limit = $paginator.TotalPages - $adjacent_links -->
    {{ $upper_limit := (sub $p.TotalPages $adjacent_links) }}

    {{- range $p.Pagers -}}
      {{ $s.Set "page_number_flag" false }}

      <!-- Complex page numbers. -->
      {{ if gt $p.TotalPages $max_links }}

        <!-- Lower limit pages. -->
        <!-- If the user is on a page which is in the lower limit.  -->
        {{ if le $p.PageNumber $lower_limit }}

          <!-- If the current loop page is less than max_links. -->
          {{ if le .PageNumber $max_links }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Upper limit pages. -->
        <!-- If the user is on a page which is in the upper limit. -->
        {{ else if ge $p.PageNumber $upper_limit }}

          <!-- If the current loop page is greater than total pages minus $max_links -->
          {{ if gt .PageNumber (sub .TotalPages $max_links) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Middle pages. -->
        {{ else }}
          
          {{ if and ( ge .PageNumber (sub $p.PageNumber $adjacent_links) ) ( le .PageNumber (add $p.PageNumber $adjacent_links) ) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        {{ end }}

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

        {{ $s.Set "page_number_flag" true }}
      {{ end }}

      <!-- Show Pager. -->
      {{- if eq ($s.Get "page_number_flag") true -}}
      <li>
        {{ if not (eq $pagenumber .PageNumber) }} 
        <a href="{{ .URL }}" class="pagination-link" 
           aria-label="Goto page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ else }}
        <a class="pagination-link is-current" 
           aria-label="Page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ end }}
      </li>
      {{- end -}}
    {{ end }}

    </ul>
  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

Hugo Pagination: Adjacent

This would result the same in any screen width.

How does it works ?

You can see the detail in bootstrap article.


6: Indicator

Goal: Add indicator, and putting all pagination part together.

This is what we want to achieve in this tutorial.

Hugo Pagination: Indicator Animation

We will achieve this with Hugo code.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/04-indicator.html" (dict "p" $paginator "s" .Scratch) }}

Partial: Pagination Indicator

Now comes, the long code. Complete code is here below:

<nav class="pagination is-small is-centered"
     role="navigation" aria-label="pagination">
  {{ $s := .s }}
  {{ $p := .p }}

  {{ if gt .p.TotalPages 1 }}
    <!-- Previous Page. -->
    {{ if .p.HasPrev }}
      <a class="pagination-previous" href="{{ .p.Prev.URL }}" 
         rel="prev">Previous</a>
    {{ else }}
      <a class="pagination-previous" title="This is the first page"
         disabled>Previous</a>
    {{ end }}

    <!-- Next Page. -->
    {{ if .p.HasNext }}
      <a class="pagination-next" href="{{ .p.Next.URL }}" 
         rel="next">Next</a>
    {{ else }}
      <a class="pagination-next" title="This is the last page"
         disabled>Next</a>
    {{ end }}

    <ul class="pagination-list">

    <!-- Page numbers. -->
    {{- $pagenumber := $p.PageNumber -}}

    <!-- Number of links either side of the current page. -->
    {{ $adjacent_links := 2 }}

    <!-- $max_links = ($adjacent_links * 2) + 1 -->
    {{ $max_links := (add (mul $adjacent_links 2) 1) }}

    <!-- $lower_limit = 1 + $adjacent_links -->
    {{ $lower_limit := (add 1 $adjacent_links) }}

    <!-- $upper_limit = $paginator.TotalPages - $adjacent_links -->
    {{ $upper_limit := (sub $p.TotalPages $adjacent_links) }}

    {{ if gt $p.TotalPages $max_links }}
      <!-- First Page. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 1 }}
      <li>
        <a href="{{ $p.First.URL }}" class="pagination-link" 
           aria-label="Goto page 1">1</a>
      </li>
      {{ end }}

      <!-- Early (More Pages) Indicator. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 2 }}
      <li>
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}
    {{ end }}

    {{- range $p.Pagers -}}
      {{ $s.Set "page_number_flag" false }}

      <!-- Complex page numbers. -->
      {{ if gt $p.TotalPages $max_links }}

        <!-- Lower limit pages. -->
        <!-- If the user is on a page which is in the lower limit.  -->
        {{ if le $p.PageNumber $lower_limit }}

          <!-- If the current loop page is less than max_links. -->
          {{ if le .PageNumber $max_links }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Upper limit pages. -->
        <!-- If the user is on a page which is in the upper limit. -->
        {{ else if ge $p.PageNumber $upper_limit }}

          <!-- If the current loop page is greater than total pages minus $max_links -->
          {{ if gt .PageNumber (sub .TotalPages $max_links) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Middle pages. -->
        {{ else }}
          
          {{ if and ( ge .PageNumber (sub $p.PageNumber $adjacent_links) ) ( le .PageNumber (add $p.PageNumber $adjacent_links) ) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        {{ end }}

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

        {{ $s.Set "page_number_flag" true }}
      {{ end }}

      <!-- Show Pager. -->
      {{- if eq ($s.Get "page_number_flag") true -}}
      <li>
        {{ if not (eq $pagenumber .PageNumber) }} 
        <a href="{{ .URL }}" class="pagination-link" 
           aria-label="Goto page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ else }}
        <a class="pagination-link is-current" 
           aria-label="Page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ end }}
      </li>
      {{- end -}}
    {{ end }}

    {{ if gt $p.TotalPages $max_links }}
      <!-- Late (More Pages) Indicator. -->
      {{ if lt (add $p.PageNumber $adjacent_links) (sub $p.TotalPages 1) }}
      <li>
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}

      <!-- Last Page. -->
      {{ if lt (add $p.PageNumber $adjacent_links) $p.TotalPages }}
      <li>
        <a href="{{ $p.Last.URL }}" class="pagination-link" 
           aria-label="Goto page {{ $p.TotalPages }}">{{ $p.TotalPages }}</a>
      </li>
      {{ end }}
    {{ end }}
    </ul>
  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

  • 480px screen wide

Hugo Pagination: Indicator

  • 640px screen wide

Hugo Pagination: Indicator

  • 800px screen wide

Hugo Pagination: Indicator

How does it works ?

You can see the detail in bootstrap article.


7: Responsive

Goal: Bringing responsive pagination, using mobile first.

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.

This is what we want to achieve in this tutorial.

Hugo Pagination: Responsive Animation

We will achieve this with Hugo code.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/05-responsive.html" (dict "p" $paginator "s" .Scratch) }}

SASS

We require this custom SASS

+tablet
  li.blog-previous a:after
    content: " previous"
  li.blog-next a:before
    content: "next "

// Breakpoint

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

// Responsiveness

ul.pagination-list
  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
  +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.first,
    li.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)

Partial: Pagination Responsive

Complete code is here below:

<nav class="pagination is-small is-centered" 
     role="navigation" aria-label="pagination">
  {{ $s := .s }}
  {{ $p := .p }}

  {{ if gt .p.TotalPages 1 }}
    <ul class="pagination-list">

    <!-- Page numbers. -->
    {{- $pagenumber := $p.PageNumber -}}

    <!-- Number of links either side of the current page. -->
    {{ $adjacent_links := 2 }}

    <!-- $max_links = ($adjacent_links * 2) + 1 -->
    {{ $max_links := (add (mul $adjacent_links 2) 1) }}

    <!-- $lower_limit = 1 + $adjacent_links -->
    {{ $lower_limit := (add 1 $adjacent_links) }}

    <!-- $upper_limit = $paginator.TotalPages - $adjacent_links -->
    {{ $upper_limit := (sub $p.TotalPages $adjacent_links) }}

      <!-- Previous Page. -->
      <li class="blog-previous">
      {{ if .p.HasPrev }}
        <a class="pagination-previous"
           href="{{ .p.Prev.URL }}" 
           rel="prev">&laquo;&nbsp;</a>
      {{ else }}
        <a class="pagination-previous"
           title="This is the first page"
           disabled>&laquo;&nbsp;</a>
      {{ end }}
      </li>

    {{ if gt $p.TotalPages $max_links }}
      <!-- First Page. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 1 }}
      <li class="first">
        <a href="{{ $p.First.URL }}" class="pagination-link" 
           aria-label="Goto page 1">1</a>
      </li>
      {{ end }}

      <!-- Early (More Pages) Indicator. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 2 }}
      <li class="pages-indicator first">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}
    {{ end }}

    {{- range $p.Pagers -}}
      {{ $s.Set "page_number_flag" false }}

      <!-- Complex page numbers. -->
      {{ if gt $p.TotalPages $max_links }}

        <!-- Lower limit pages. -->
        <!-- If the user is on a page which is in the lower limit.  -->
        {{ if le $p.PageNumber $lower_limit }}

          <!-- If the current loop page is less than max_links. -->
          {{ if le .PageNumber $max_links }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Upper limit pages. -->
        <!-- If the user is on a page which is in the upper limit. -->
        {{ else if ge $p.PageNumber $upper_limit }}

          <!-- If the current loop page is greater than total pages minus $max_links -->
          {{ if gt .PageNumber (sub .TotalPages $max_links) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Middle pages. -->
        {{ else }}
          
          {{ if and ( ge .PageNumber (sub $p.PageNumber $adjacent_links) ) ( le .PageNumber (add $p.PageNumber $adjacent_links) ) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        {{ end }}

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

        {{ $s.Set "page_number_flag" true }}
      {{ end }}

      {{- if eq ($s.Get "page_number_flag") true -}}
      <!-- Calculate Offset Class. -->
        {{ $s.Set "page_offset" (sub .PageNumber $p.PageNumber) }}

        {{ $s.Set "page_offset_class" "" }}
        {{- if ge ($s.Get "page_offset") 0 -}}
          {{ $s.Set "page_offset_class" (print "pagination--offset-" ($s.Get "page_offset") ) }}
        {{- else -}}
          {{ $s.Set "page_offset_class" (print "pagination--offset" ($s.Get "page_offset") ) }}
        {{- end -}}

      <!-- Show Pager. -->
      <li class="{{ $s.Get "page_offset_class" }}">
        {{ if not (eq $pagenumber .PageNumber) }} 
        <a href="{{ .URL }}" class="pagination-link" 
           aria-label="Goto page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ else }}
        <a class="pagination-link is-current" 
           aria-label="Page {{ .PageNumber }}">
          {{ .PageNumber }}
        </a>
        {{ end }}
      </li>
      {{- end -}}
    {{ end }}

    {{ if gt $p.TotalPages $max_links }}
      <!-- Late (More Pages) Indicator. -->
      {{ if lt (add $p.PageNumber $adjacent_links) (sub $p.TotalPages 1) }}
      <li class="pages-indicator last">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}

      <!-- Last Page. -->
      {{ if lt (add $p.PageNumber $adjacent_links) $p.TotalPages }}
      <li class="last">
        <a href="{{ $p.Last.URL }}" class="pagination-link" 
           aria-label="Goto page {{ $p.TotalPages }}">{{ $p.TotalPages }}</a>
      </li>
      {{ end }}
    {{ end }}

      <!-- Next Page. -->
      <li class="blog-next">
      {{ if .p.HasNext }}
        <a class="pagination-next"
           href="{{ .p.Next.URL }}" 
           rel="next">&nbsp;&raquo;</a>
      {{ else }}
        <a class="pagination-next"
           title="This is the last page"
           disabled>&nbsp;&raquo;</a>
      {{ end }}
      </li>
    </ul>
  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

  • 480px screen wide

Hugo Pagination: Responsive

  • 640px screen wide (cropped)

Hugo Pagination: Responsive

  • 800px screen wide (cropped)

Hugo Pagination: Responsive

How does it works ?

You can see the detail in bootstrap article.


8: Screenreader

Goal: Bringing screen reader accessability in pagination.

There will be no such change for the look. It will remain the same as responsive pagination.

Screenreader Class

I just follow bulma guidance:

To hidden content visually, you simply need to add is-sr-only.

<span class="is-sr-only">Hidden Content</span>

Alternatively you can use fontawesome class that is similar to bootstrap.

<span class="sr-only">Hidden Content</span>

This content can be read by screenreader.

Layout: List

Change our previous blog list to use this paginator below:

  • themes/tutor-05/layouts/archives/list.html.
  {{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
  {{ partial "pagination/06-screenreader.html" (dict "p" $paginator "s" .Scratch) }}

Partial: Pagination Screenreader

Complete code is here below:

<nav class="pagination is-small is-centered" 
     role="navigation" aria-label="pagination">
  {{ $s := .s }}
  {{ $p := .p }}

  {{ if gt .p.TotalPages 1 }}
    <ul class="pagination-list">

    <!-- Page numbers. -->
    {{- $pagenumber := $p.PageNumber -}}

    <!-- Number of links either side of the current page. -->
    {{ $adjacent_links := 2 }}

    <!-- $max_links = ($adjacent_links * 2) + 1 -->
    {{ $max_links := (add (mul $adjacent_links 2) 1) }}

    <!-- $lower_limit = 1 + $adjacent_links -->
    {{ $lower_limit := (add 1 $adjacent_links) }}

    <!-- $upper_limit = $paginator.TotalPages - $adjacent_links -->
    {{ $upper_limit := (sub $p.TotalPages $adjacent_links) }}

      <!-- Previous Page. -->
      <li class="blog-previous">
      {{ if .p.HasPrev }}
        <a class="pagination-previous"
           href="{{ .p.Prev.URL }}" 
           rel="prev">&laquo;&nbsp;
           <span class="is-sr-only">Previous</span>
        </a>
      {{ else }}
        <a class="pagination-previous"
           title="This is the first page"
           disabled>&laquo;&nbsp;</a>
      {{ end }}
      </li>

    {{ if gt $p.TotalPages $max_links }}
      <!-- First Page. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 1 }}
      <li class="first">
        <a href="{{ $p.First.URL }}" class="pagination-link" 
           aria-label="Goto page 1">
           <span class="is-sr-only">Goto page </span>1</a>
      </li>
      {{ end }}

      <!-- Early (More Pages) Indicator. -->
      {{ if gt (sub $p.PageNumber $adjacent_links) 2 }}
      <li class="pages-indicator first">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}
    {{ end }}

    {{- range $p.Pagers -}}
      {{ $s.Set "page_number_flag" false }}

      <!-- Complex page numbers. -->
      {{ if gt $p.TotalPages $max_links }}

        <!-- Lower limit pages. -->
        <!-- If the user is on a page which is in the lower limit.  -->
        {{ if le $p.PageNumber $lower_limit }}

          <!-- If the current loop page is less than max_links. -->
          {{ if le .PageNumber $max_links }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Upper limit pages. -->
        <!-- If the user is on a page which is in the upper limit. -->
        {{ else if ge $p.PageNumber $upper_limit }}

          <!-- If the current loop page is greater than total pages minus $max_links -->
          {{ if gt .PageNumber (sub .TotalPages $max_links) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        <!-- Middle pages. -->
        {{ else }}
          
          {{ if and ( ge .PageNumber (sub $p.PageNumber $adjacent_links) ) ( le .PageNumber (add $p.PageNumber $adjacent_links) ) }}
            {{ $s.Set "page_number_flag" true }}
          {{ end }}

        {{ end }}

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

        {{ $s.Set "page_number_flag" true }}
      {{ end }}

      {{- if eq ($s.Get "page_number_flag") true -}}
      <!-- Calculate Offset Class. -->
        {{ $s.Set "page_offset" (sub .PageNumber $p.PageNumber) }}

        {{ $s.Set "page_offset_class" "" }}
        {{- if ge ($s.Get "page_offset") 0 -}}
          {{ $s.Set "page_offset_class" (print "pagination--offset-" ($s.Get "page_offset") ) }}
        {{- else -}}
          {{ $s.Set "page_offset_class" (print "pagination--offset" ($s.Get "page_offset") ) }}
        {{- end -}}

      <!-- Show Pager. -->
      <li class="{{ $s.Get "page_offset_class" }}">
        {{ if not (eq $pagenumber .PageNumber) }} 
        <a href="{{ .URL }}" class="pagination-link" 
           aria-label="Goto page {{ .PageNumber }}">
          <span class="is-sr-only">Goto page </span>{{ .PageNumber }}
        </a>
        {{ else }}
        <a class="pagination-link is-current" 
           aria-label="Page {{ .PageNumber }}">
          <span class="is-sr-only">Page </span>{{ .PageNumber }}
        </a>
        {{ end }}
      </li>
      {{- end -}}
    {{ end }}

    {{ if gt $p.TotalPages $max_links }}
      <!-- Late (More Pages) Indicator. -->
      {{ if lt (add $p.PageNumber $adjacent_links) (sub $p.TotalPages 1) }}
      <li class="pages-indicator last">
        <span class="pagination-ellipsis">&hellip;</span>
      </li>
      {{ end }}

      <!-- Last Page. -->
      {{ if lt (add $p.PageNumber $adjacent_links) $p.TotalPages }}
      <li class="last">
        <a href="{{ $p.Last.URL }}" class="pagination-link" 
           aria-label="Goto page {{ $p.TotalPages }}">
           <span class="is-sr-only">Goto page </span>{{ $p.TotalPages }}</a>
      </li>
      {{ end }}
    {{ end }}

      <!-- Next Page. -->
      <li class="blog-next">
      {{ if .p.HasNext }}
        <a class="pagination-next"
           href="{{ .p.Next.URL }}" 
           rel="next">&nbsp;&raquo;
           <span class="is-sr-only">Next</span>
        </a>
      {{ else }}
        <a class="pagination-next"
           title="This is the last page"
           disabled>&nbsp;&raquo;</a>
      {{ end }}
      </li>
    </ul>
  {{ end }}
</nav>

Browser: Pagination Preview

Consider check out the result:

  • 480px screen wide

Hugo Pagination: Screenreader

How does it works ?

You can see the detail in bootstrap article.


What is Next ?

Now the pagination tutorial is done. I think this is all for now.

Just like this adorable kitten, you may feel excited. Consider resume our tutorial.

adorable kitten

There are still some interesting topic, about Content in Hugo such as Page Post. Consider continue reading [ Hugo - Content ].

Thank you for reading.