Building Improved List Page Navigation for Hugo

Published: 2022 April 05

Last edited: 2022 June 04

software development web development user interface static site generator Hugo Hugo theme Bootstrap Font Awesome

Note of Caution

The approach detailed in this post has some problems and produces confusing results for subsection list pages.

It was replaced and superceded by the approach used in this post.

Update Note

When this post was originally published, it linked to a dynamic version of the All Posts list page. That page has been retired. Consequently, links to that page have been replaced with a links to a saved static version of that page.

Introduction

This project is built with Hugo and uses the Minimal Hugo theme.

This post is part of an ongoing effort to tailor the theme over time.

Objective

In this post we’ll build a new user interface for navigating between list pages.

As of this writing, the list page has right and left arrows that allow navigating to the list pages for earlier and later posts. We’ll keep those, and add a count of the list pages to provide some context, as well as adding a link to the All Posts list page.

We built elements of this in previous posts:

Now, we’ll incorporate those elements into a new working interface for the site.

Building the new navigation interface

Step 1 - Adding the basic structure

Because list pages in Hugo are built with layout files, this will involve updating the Hugo theme’s paginator.html file, which is in the /layouts/partials/ directory.

We’ll add the new features below the existing paginator elements.

To start, we’ll copy the code from prototype 7 of Testing CSS Grid post (removing the -proto7 suffix from element IDs), and add it to the paginator.html file:

<div id="listpage-navigation-container">
    <div id="listpage-navigation-panel">
        <a id="listpage-navigation-left" href="">Left Navigation</a>
        <div id="listpage-navigation-pagexofy">List Page X of Y</div>
        <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See All Z Posts</a></div>
        <a id="listpage-navigation-right" href="">Right Navigation</a>
    </div>
</div>

Similarly, we’ll add the CSS from that prototype to the custom.css file in our /static/css/ directory that we created in the Changing the Spacing of Font Awesome Icons in Hugo post:

/* List Page Navigation Interface */

div#listpage-navigation-container {
    display: grid;
    justify-content: center;
    grid-template-columns: minmax(50px, auto);
}

div#listpage-navigation-panel {
    display: grid;
    grid-template-areas: 
        "left pagexofy right"
        "left allpostlink right";
    grid-template-columns: repeat(3, minmax(50px, 300px));
    justify-items: stretch;
}

a#listpage-navigation-left {
    grid-area: left;
    text-align: center;
    
    display: flex;
    align-items: center;
    justify-content: center;
}

div#listpage-navigation-pagexofy {
    grid-area: pagexofy;
    text-align: center;
    
    display: flex;
    align-items: center;
    justify-content: center;
}

div#listpage-navigation-allpostlink {
    grid-area: allpostlink;
    text-align: center;
    
    display: flex;
    align-items: center;
    justify-content: center;
}

a#listpage-navigation-right {
    grid-area: right;
    text-align: center;
    
    display: flex;
    align-items: center;
    justify-content: center;
}

Step 2 - Incorporating the existing Hugo conditional logic

We’ll integrate the conditional logic from the current paginator.

{{ if or .Paginator.HasPrev .Paginator.HasNext }}

    <div id="listpage-navigation-container">
        <div id="listpage-navigation-panel">

            {{ if .Paginator.HasPrev }}
                <a id="listpage-navigation-left" href="">Left Navigation</a>
            {{ else }}
                <a id="listpage-navigation-left" href="">Beginning</a>
            {{ end }}

            <div id="listpage-navigation-pagexofy">List Page X of Y</div>
            <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See All Z Posts</a></div>

            {{ if .Paginator.HasNext }}
                <a id="listpage-navigation-right" href="">Right Navigation</a>
            {{ else }}
                <a id="listpage-navigation-right" href="">End</a>
            {{ end }}
        </div>
    </div>

{{ end }}

We’ll integrate the link and page count logic from the current paginator.

{{ if or .Paginator.HasPrev .Paginator.HasNext }}

    <div id="listpage-navigation-container">
        <div id="listpage-navigation-panel">

            {{ if .Paginator.HasPrev }}
                <a id="listpage-navigation-left" href="{{ .Paginator.Prev.URL }}" rel="prev">Left Navigation</a>
            {{ else }}
                <a id="listpage-navigation-left" href="">Beginning</a>
            {{ end }}

            <div id="listpage-navigation-pagexofy">List page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}.</div>
            <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See All Z Posts</a></div>

            {{ if .Paginator.HasNext }}
                <a id="listpage-navigation-right" href="{{ .Paginator.Next.URL }}" rel="next">Right Navigation</a>
            {{ else }}
                <a id="listpage-navigation-right" href="">End</a>
            {{ end }}
        </div>
    </div>

{{ end }}

Step 4 - Incorporating the section page count logic

We’ll integrate logic for counting the total number of pages in a section.

{{ if or .Paginator.HasPrev .Paginator.HasNext }}

    <div id="listpage-navigation-container">
        <div id="listpage-navigation-panel">

            {{ if .Paginator.HasPrev }}
                <a id="listpage-navigation-left" href="{{ .Paginator.Prev.URL }}" rel="prev">Left Navigation</a>
            {{ else }}
                <a id="listpage-navigation-left" href="">Beginning</a>
            {{ end }}

            <div id="listpage-navigation-pagexofy">List page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}.</div>
            <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See all {{ .Paginator.TotalNumberOfElements }} posts.</a></div>

            {{ if .Paginator.HasNext }}
                <a id="listpage-navigation-right" href="{{ .Paginator.Next.URL }}" rel="next">Right Navigation</a>
            {{ else }}
                <a id="listpage-navigation-right" href="">End</a>
            {{ end }}
        </div>
    </div>

{{ end }}

Step 5 - Incorporating the Font Awesome icons

We’ll integrate the Font Awesome icons from the current paginator.

{{ if or .Paginator.HasPrev .Paginator.HasNext }}

    <div id="listpage-navigation-container">
        <div id="listpage-navigation-panel">

            {{ if .Paginator.HasPrev }}
                <a id="listpage-navigation-left" href="{{ .Paginator.Prev.URL }}" rel="prev">
                    <i class="fa fa-arrow-left fa-3x"></i>
                </a>
            {{ else }}
                <a id="listpage-navigation-left" href="">Beginning</a>
            {{ end }}

            <div id="listpage-navigation-pagexofy">List page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}.</div>
            <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See all {{ .Paginator.TotalNumberOfElements }} posts.</a></div>

            {{ if .Paginator.HasNext }}
                <a id="listpage-navigation-right" href="{{ .Paginator.Next.URL }}" rel="next">
                    <i class="fa fa-arrow-right fa-3x"></i>
                </a>
            {{ else }}
                <a id="listpage-navigation-right" href="">End</a>
            {{ end }}
        </div>
    </div>

{{ end }}

Step 6 - Incorporating theme styling

We’ll integrate element class declarations from the current paginator to produce consistent styling.

{{ if or .Paginator.HasPrev .Paginator.HasNext }}

    <div id="listpage-navigation-container">
        <div id="listpage-navigation-panel">

            {{ if .Paginator.HasPrev }}
                <a id="listpage-navigation-left" class="icon pages-icon" href="{{ .Paginator.Prev.URL }}" rel="prev">
                    <i class="fa fa-arrow-left fa-3x"></i>
                </a>
            {{ else }}
                <a id="listpage-navigation-left" class="icon pages-icon" href="">Beginning</a>
            {{ end }}

            <div id="listpage-navigation-pagexofy">List page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}.</div>
            <div id="listpage-navigation-allpostlink"><a href="/map/all-posts/">See all {{ .Paginator.TotalNumberOfElements }} posts.</a></div>

            {{ if .Paginator.HasNext }}
                <a id="listpage-navigation-right" class="icon pages-icon" href="{{ .Paginator.Next.URL }}" rel="next">
                    <i class="fa fa-arrow-right fa-3x"></i>
                </a>
            {{ else }}
                <a id="listpage-navigation-right" class="icon pages-icon" href="">End</a>
            {{ end }}
        </div>
    </div>

{{ end }}

Step 7 - Commenting out the previous paginator code

Now that we’ve built a new interface for list page navigation we can comment out the code for the previous version.

Conclusion

This improved interface is better suited to the current needs of the project. (At the time of this writing it can be seen at the bottom of the list page, just above the header.)

There are still several areas for improvement:

Copying Directory Structure With a Bash Script - With Help From ChatGPT AI

Published: 2024 January 22

Backing Up Git Config Values With a Bash Script

Published: 2023 August 25

Backing Up Visual Studio Code (VS Code) Settings and Extensions With a Bash Script

Published: 2022 November 09