Customise list pages | Hugo Elliott

Customise list pages

Hugo Elliott

| website | hugo | Est reading time: 7 mins

How to customise list pages

Hugo’s default list page shows an un-ordered list with links to each blog post. I want to change this to look better.

I want to create a template list page that displays the

  • Featured image
  • Post title, and
  • Tags

and that when you click on a Tag (or Category) it takes you to a list page showing a list of all posts with that Tag (or Category)

1. Create a blank page to hold the lists

Create a file layouts/blog/list.html and insert the following code

{{ define "main" }}
    <div class="container">
    </div>
{{ end }}

Navigate to http://localhost:1313/blog/ - the list of blog posts has disappeared meaning that this page is being displayed correctly.

2. Create a postcard that can be used in the list pages

Rather than adding lots of code to list.html - we’re going to add a widget that we can reference.

Create and open the file layouts/partials/widgets/postcard.html adding

{{ $featuredImageUrl := .Params.featuredImageUrl }}
{{ $featuredAltText := .Params.featuredImageAltText }}
{{ $permalink := .Permalink }}
<div class="card">
    <div class="card-image">
        <figure class="image is-4by3">
            {{ with .Params.featuredImageUrl }}
            <a href="{{ $permalink }}"><img src="{{ $featuredImageUrl }}" alt="{{ $featuredAltText }} loading="lazy""></a>
            {{ end }}
        </figure>
    </div>
    <div class="card-content">
        <a class="title is-5" href="{{ $permalink}}">{{ .Title }}</a>
        {{ with .Params.tags }}
        <p class="is-size-7 has-text-grey-light mt-1">
            {{ range . }}
                <i class="fas fa-tag"></i>
                {{ $href := print (absURL "tags/") (urlize .) }}
                <a href="{{ $href }}">{{ . }}</a>
            {{ end }}
        </p>
        {{ end }}
    </div>
</div>

This code does a couple of things, it

  1. Pulls the featured image & title from each post and inserts them into the post card
  2. Adds the tags in each post as clickable links

3. Edit the list pages to show post cards

Edit layouts/blog/list.html adding

{{ define "main" }}
    <div class="container pt-3 pl-1 pr-1 pb-3">
        <h1 class="title ">{{ .Title }}</h1>
        <div class="columns is-multiline mt-2">
            {{ range .Paginator.Pages.ByPublishDate.Reverse }}
            <div class="column is-one-third">
                {{ partial "widgets/postcard.html" . }}
            </div>
            {{ end }}
        </div>
    </div>
{{ end }}

Navigate to http://localhost:1313/blog/, your page should look something like this

list page in Hugo

Please note I’ve created three blog posts which show up here on the list page.

4. Add pagination to the list pages

There are some great articles on pagination in Hugo such as this and this, but given I’m using Bulma then PaksTech’s solution works perfectly.

The default pagination in Hugo is to list 10 items per page. You can change this in config.toml adding

paginate = 6

Create and open partials/widgets/paginantion.html and add the following

{{ $pag := $.Paginator }}
{{ if gt $pag.TotalPages 1 }}
<nav class="pagination">
<ul class="pagination-list">
    {{ with $pag.First }}
    <li>
        <a href="{{ .URL }}" class="pagination-link" {{ if not $pag.HasPrev }} disabled{{ end }} aria-label="First"><span aria-hidden="true">&laquo;&laquo;</span></a>
    </li>
    {{ end }}
    <li>
        <a href="{{ if $pag.HasPrev }}{{ $pag.Prev.URL }}{{ end }}" class="pagination-link" {{ if not $pag.HasPrev }} disabled{{ end }} aria-label="Previous"><span aria-hidden="true">&laquo;</span></a>
    </li>
    {{ $ellipsed := false }}
    {{ $shouldEllipse := false }}
    {{ range $pag.Pagers }}
    {{ $right := sub .TotalPages .PageNumber }}
    {{ $showNumber := or (le .PageNumber 3) (eq $right 0) }}
    {{ $showNumber := or $showNumber (and (gt .PageNumber (sub $pag.PageNumber 2)) (lt .PageNumber (add $pag.PageNumber 2)))  }}
    {{ if $showNumber }}
        {{ $ellipsed = false }}
        {{ $shouldEllipse = false }}
    {{ else }}
        {{ $shouldEllipse = not $ellipsed }}
        {{ $ellipsed = true }}
    {{ end }}
    {{ if $showNumber }}
    <li><a class="pagination-link {{ if eq . $pag }}is-current{{ end }}" href="{{ .URL }}">{{ .PageNumber }}</a></li>
    {{ else if $shouldEllipse }}
    <li class="pagination-link" disabled><span aria-hidden="true">&nbsp;&hellip;&nbsp;</span></li>
    {{ end }}
    {{ end }}
    <li>
    <a href="{{ if $pag.HasNext }}{{ $pag.Next.URL }}{{ end }}" class="pagination-link" {{ if not $pag.HasNext }}disabled{{ end }} aria-label="Next"><span aria-hidden="true">&raquo;</span></a>
    </li>
    {{ with $pag.Last }}
    <li>
        <a href="{{ .URL }}" class="pagination-link" {{ if not $pag.HasNext }}disabled{{ end }} aria-label="Last"><span aria-hidden="true">&raquo;&raquo;</span></a>
    </li>
    {{ end }}
</ul>
</nav>
{{ end }}

To use this code, you need to add the following to the list template page

{{ partial "widgets/pagination.html" . }}

Then open and edit layouts/blog/list.html to read

{{ define "main" }}
<div class="container pt-3 pl-1 pr-1 pb-3">
    <h1 class="title ">{{ .Title }}</h1>
    <div class="columns is-multiline mt-2">
        {{ range .Paginator.Pages.ByPublishDate.Reverse }}
        <div class="column is-one-third">
            {{ partial "widgets/postcard.html" . }}
        </div>
        {{ end }}
    </div>
    <div class="columns is-centered mt-2">
        <div class="column is-narrow">
            {{ partial "widgets/pagination.html" . }}
        </div>
    </div>
</div>
{{ end }}

If you have enough blog posts, you will see the pagination show on all list pages with more the (in this case) 6 posts, such as this one below

Pagination on list pages

Open and edit config.toml and add the following

[menu]
    ...
    [[menu.taxonomy]]
        name = "Tags"
        url = "/tags"
    [[menu.taxonomy]]
        name = "Categories"
        url = "/categories"

Open and edit partials/footer.html and add the following

<footer class="footer">
    <div class="container">
        <div class="has-text-centered is-size-7-mobile pb-05">
            {{ range .Site.Menus.foot }}
            <a href="{{ .URL }}" title="{{ .Name }}">
                {{ .Name }}
            </a>
            {{ end }}
            |
            {{ range .Site.Menus.taxonomy }}
            <a href="{{ .URL }}" title="{{ .Name }}">
                {{ .Name }}
            </a>
            {{ end }}
       </div>
    </div>
    ...
</footer>

This code in the footer adds links to the static pages (About, Contact and Privacy) as well as two list pages of tags and categories.

The footer now looks like this

Updated footer

And if you click on the link to ‘Categories’ you see this

Updated category page

You would see something similar if you clicked on the link to ‘Tags’

6. Customizing the Category and Tag list pages

If you now click on one one of the postcards, it takes you through to a page listing all the posts with that Category.

Updated category list page

I think this page should be updated to include whether its a Category or Tag, and a back button.

Create and edit layouts/_default/category.html and add the following

{{ define "main" }}
    {{ partial "widgets/taxonomy.html" . }}
{{ end }}

Create and edit layouts/_default/tag.html and add the following

{{ define "main" }}
    {{ partial "widgets/taxonomy.html" . }}
{{ end }}

Create and edit partials/widgets/taxonomy.html and add the following

{{ $taxonomies := title (index (split (delimit (split .Permalink "/") "," "") "," ) 3 ) }}
{{ $taxonomy := title (index (split (delimit (split .Permalink "/") "," "") "," ) 3 ) | singularize }}

<!-- Get the URL of the page, it'll be in the form http://example.com/taxonomies/taxonomy-name -->
{{ $url := urls.Parse .Permalink }}
<!-- Find the total length of URL = 38 -->
{{ $a := len .Permalink}}
<!-- find length of last part the URL and add 1 -->
{{ $lastUrlElement := index (last 1 (split (delimit (split .Permalink "/") "," "") ",")) 0 }}
{{ $d := len $lastUrlElement}}
{{ $e := add $d 1 }}
<!-- subtract the length of the last part (+1) from the total length of the URL -->
{{ $f := sub $a $e}}
<!-- extract the first $f characters of the URL  -->
{{ $first := first $f .Permalink}}

<div class="container pt-3 pl-1 pr-1 pb-3">
<div class="content">
    <h1>{{ $taxonomy }}: {{ .Title }}</h1>
    {{ .Content }}
</div>
<div class="columns is-multiline">
    {{ range .Paginator.Pages }}
    <div class="column is-one-third">
        {{ partial "widgets/postcard.html" . }}
    </div>
    {{ end }}
</div>
<div class="columns is-centered">
    <div class="column is-narrow">
        {{ partial "widgets/pagination.html" . }}
    </div>
</div>
    <a href="{{ $first }}" class="button is-link">Back to {{ $taxonomies }}</a>
</div>

The first part of this code I’m extracting from the URL string the taxonomy name ie “taxonomies” from this URL http://example.com/taxonomies/taxonomy-name and then singularising it. Then I’m insterting it into a ‘back button’ to go back to updated Category and Tag list pages.

Updated category list page

This looks a little better… I think.

Next I’m going to add links to related content, the ability to comment on posts, and build a widget to collect email addresses.

Previous post

Adding static pages

Next post

Related content
.

Comments

comments powered by Disqus