Preface
Goal: A Simple Pagination.
1: Prepare
Pagination can be set in config.toml
-
- config.toml
- gitlab.com/…/config.toml
Paginate = 7
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") }}
While debugging, or development process, we can do this to override sitewide paginate configuration. Here we use 5 articles for each pagination page.
{{ $paginator := .Paginate (where .Site.Pages "Type" "post") 5 }}
This is a very helpful trick for me.
2: Preview: General
This is what we want to achieve in this tutorial.
HTML Preview
The HTML that we want to achieve in this article, is similar as below.
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<span class="page-link">First</span>
</li>
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
<li class="page-item disabled">
<span class="page-link">Page: 1 of 3</span>
</li>
<li class="page-item">
<a class="page-link" href="/pages/page/2/" rel="next">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="/pages/page/3/" rel="last">Last</a>
</li>
</ul>
We will achieve this with Hugo code.
3: Layout
Change our previous blog list
- themes/tutor-05/layouts/archives/list.html.
{{ $posts := where .Site.Pages "Type" "post" }}
<section id="archive">
<div class="post-list">
{{ range $posts }}
{{ partial "summary-blog-list.html" . }}
{{ end }}
</div>
</section>
to use paginator
{{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
{{ partial "pagination-simple.html" (dict "p" $paginator) }}
<section id="archive">
<div class="post-list">
{{ range $paginator.Pages }}
{{ partial "summary-blog-list.html" . }}
{{ end }}
</div>
</section>
Layout: List
The complete file is here below:
-
- themes/tutor-05/layouts/archives/list.html
- gitlab.com/…/layouts/archives/list.html.
{{ define "main" }}
<main role="main"
class="container-fluid m-3 m-sm-0 p-3
bg-light rounded border border-dark shadow-hover">
<header>
<h4>{{ .Title | default .Site.Title }}</h4>
</header>
<article>
{{ .Content }}
</article>
{{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
{{ partial "pagination-simple.html" (dict "p" $paginator) }}
<section id="archive">
<div class="post-list">
{{ range $paginator.Pages }}
{{ partial "summary-blog-list.html" . }}
{{ end }}
</div>
</section>
</main>
{{ 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) }}
4: Navigation: Previous and Next
No need to show any pagination navigation, if we what we have is only one page. Hence our minimal pagination logic would be:
<nav aria-label="Page navigation">
{{ if gt .p.TotalPages 1 }}
<ul class="pagination justify-content-center">
...
</ul>
{{ end }}
</nav>
Of course this is not enough. Our minimal pagination should show something.
Partial: Pagination Simple
- themes/tutor-05/layouts/partials/pagination-simple.html : gitlab.com/…/partials/pagination-simple.html.
<nav aria-label="Page navigation">
{{ if gt .p.TotalPages 1 }}
<ul class="pagination justify-content-center">
<!-- Previous Page. -->
{{ if .p.HasPrev }}
<li class="page-item">
<a class="page-link" href="{{ .p.Prev.URL }}"
rel="prev">Previous</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
{{ end }}
<!-- Next Page. -->
{{ if .p.HasNext }}
<li class="page-item">
<a class="page-link" href="{{ .p.Next.URL }}"
rel="next">Next</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Next</span>
</li>
{{ end }}
</ul>
{{ end }}
</nav>
Browser: Pagination Preview
How does it works ?
This code above rely on
-
Previous Page: if .HasPrev, and
-
Next Page: if .HasNext.
This should be self explanatory.
Stylesheet: Bootstrap Class
Bootstrap specific class are these below
-
ul: pagination
-
li: page-item
-
a, span: page-link
-
li: disabled
5: Navigation: First and Last
Consider also add first page and last page.
<nav aria-label="Page navigation">
{{ if gt .p.TotalPages 1 }}
<ul class="pagination justify-content-center">
<!-- First Page. -->
{{ if not (eq .p.PageNumber 1) }}
<li class="page-item">
<a class="page-link" href="{{ .p.First.URL }}"
rel="first">First</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">First</span>
</li>
{{ end }}
...
<!-- Last Page. -->
{{ if not (eq .p.PageNumber .p.TotalPages) }}
<li class="page-item">
<a class="page-link" href="{{ .p.Last.URL }}"
rel="last">Last</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Last</span>
</li>
{{ end }}
</ul>
{{ end }}
</nav>
Browser: Pagination Preview
How does it works ?
Since there is no equivalent for .HasPrev and .HasNext to show first page and last page, we utilize:
-
First Page: .PageNumber == 1.
-
Last Page: .PageNumber == .TotalPages.
6: Active Page Indicator
And also the pagination positioning in between, in the middle of those.
<nav aria-label="Page navigation">
{{ if gt .p.TotalPages 1 }}
<ul class="pagination justify-content-center">
...
<!-- Indicator Number. -->
<li class="page-item">
<span class="page-link">
Page: {{ .p.PageNumber }} of {{ .p.TotalPages }}</span>
</li>
...
</ul>
{{ end }}
</nav>
Browser: Pagination Preview
How does it works ?
This just show:
Page: {{ .p.PageNumber }} of {{ .p.TotalPages }}
7: Summary
Complete code is here below:
- themes/tutor-05/layouts/partials/pagination-simple.html : gitlab.com/…/partials/pagination-simple.html.
<nav aria-label="Page navigation">
{{ if gt .p.TotalPages 1 }}
<ul class="pagination justify-content-center">
<!-- First Page. -->
{{ if not (eq .p.PageNumber 1) }}
<li class="page-item">
<a class="page-link" href="{{ .p.First.URL }}"
rel="first">First</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">First</span>
{{ end }}
<!-- Previous Page. -->
{{ if .p.HasPrev }}
<li class="page-item">
<a class="page-link" href="{{ .p.Prev.URL }}"
rel="prev">Previous</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
{{ end }}
<!-- Indicator Number. -->
<li class="page-item disabled">
<span class="page-link">
Page: {{ .p.PageNumber }} of {{ .p.TotalPages }}</span>
</li>
<!-- Next Page. -->
{{ if .p.HasNext }}
<li class="page-item">
<a class="page-link" href="{{ .p.Next.URL }}"
rel="next">Next</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Next</span>
</li>
{{ end }}
<!-- Last Page. -->
{{ if not (eq .p.PageNumber .p.TotalPages) }}
<li class="page-item">
<a class="page-link" href="{{ .p.Last.URL }}"
rel="last">Last</a>
</li>
{{ else }}
<li class="page-item disabled">
<span class="page-link">Last</span>
</li>
{{ end }}
</ul>
{{ end }}
</nav>
What is Next ?
Just like this adorable kitten, you may feel excited. Consider resume our tutorial.
There are, some interesting topic about Pagination in Hugo. Consider continue reading [ Hugo - Pagination - Number ].
Thank you for reading.