Skip to main content
  1. 2022/
  2. July/

Hugo Tag Cloud Howto

Why do I care? What are Tags? What is a TagCloud? #

Tags
Think of tags like… Metadata. These are attributes you may associate with any content in Hugo, so as to make it easier to coalesce/reference for future you.
Tag Cloud
You’ve ABSOLUTELY seen one of these before. It may just be that you’ve not really paid any attention to it.

So what’re we doing here? #

This post by Mert Bakir is where most of the content here came from, I’ve just adapted it to my needs, but In this post, We will explain how to get tags of specific pages and How to generate a tag cloud.

Tags are a native taxonomy in Hugo, so we don’t need any special configuration to use them, We just list them a page’s front-matter:

tags: ["hugo", "tags"]
From this frontmatter snippit, Hugo will create tags/hugo and tags/tags pages for us. These pages are called term pages and the /tags is a taxonomy page.
Tangent! This is a different topic altogether.
If you want to change these pages you need to create templates For the tags and term pages.
Respectively /layouts/tags/list.html and /layouts/tags/term.html. Mert wrote a bit about Hugo templates in
this post and this post

Render the Tags of a page #

To achieve the first one, Lets created a partial called get_tags.html:

This code:

  • Gets the tags from the page’s frontmatter.
  • Sorts them alphabetically
  • Returns HTML links which include the hash “#” symbol at the beginning of each tagname.
  • Styling will come from the CSS.
1
2
3
4
5
6
7
{{- with .Param "tags" -}}
  {{- range $index, $tag := (. | sort) -}} 
    {{- with $.Site.GetPage (printf "/%s/%s" "tags" $tag) -}}
      <a class="gettag tag_{{- $tag|safeCSS }}" href="{{ .Permalink }}">#{{- $tag | urlize -}}</a>
    {{- end -}}
  {{- end -}}
{{- end -}}

Generate and display a Tag Cloud #

To create a tag-cloud Mert found two solutions online, both work.

Customization is a…. little awkward.

I want to sort the resulting blog of tags numerically, but I’ve yet to figure it out. More work!

This was asked Here, on the Hugo forums Where someone snarkily pointed at the hugo taxonomy template documentation

They seemed to indicate it should be easy… I must be dumb, however, as it makes no sense to me ….. yet.

What I’m doing: #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<div class="tagcloud taxcloud bucket">
  {{- /*  https://gohugo.io/templates/taxonomy-templates/#taxonomy-methods 
    site.params.tagCloud:
    style: 'button'
    largestFontSize: 1.75
    smallestFontSize: 0.25
    minimumMatches: 1
  */ -}}
  {{- if ne (len $.Site.Taxonomies.tags) 0 -}}
    {{- $largestFontSize := $.Site.Params.tagcloud.largestfontsize | default 1.6 -}}
    {{- $smallestFontSize := $.Site.Params.tagcloud.smallestfontsize | default  0.5 -}}
    {{- $fontSpread := sub $largestFontSize $smallestFontSize -}}
    {{- $max := add (len (index $.Site.Taxonomies.tags.ByCount 0).Pages) 1 -}}
    {{- $min := len (index $.Site.Taxonomies.tags.ByCount.Reverse 0).Pages -}}
    {{- $minMatch := $.Site.Params.tagcloud.minimummatches | default 0 -}}
    {{- $spread := sub $max $min -}}
    {{- $fontStep := div $fontSpread $spread -}}
    {{- range $name, $taxonomy := $.Site.Taxonomies.tags -}}
      {{- $tagCount := len $taxonomy.Pages -}}
      {{- if and (le  $tagCount $minMatch)  -}}
        {{- /* warnidf "tagcloud-01" "[TAGCLOUD] $.Site.Params.tagCloud.minimumMatches has current value of %i. Excluding %q from tag cloud, as it has %s matches." $.Site.Params.tagCloud.minimumMatches $name $tagCount */ -}}
      {{- else -}}
        {{- $currentFontSize := (add $smallestFontSize (mul (sub $tagCount $min) $fontStep) ) -}}
        {{- $weigth := div (sub (math.Log $tagCount) (math.Log $min)) (sub (math.Log $max) (math.Log $min)) -}}
        {{- $currentFontSize := (add $smallestFontSize (mul (sub $largestFontSize $smallestFontSize) $weigth)) -}}
        {{- if  eq $.Site.Params.tagCloud.style  "button"  -}}
          <a class="tag-button_link tagcloud-item tag-button" style="font-size: {{ $currentFontSize }}rem;" href="{{ "/tags/" | relURL }}{{ $name | urlize }}"> <span class="gdoc-tag gdoc-tax tax-button">{{ $name }}<sup>{{ $tagCount }}</sup>
          </span></a>
        {{- else -}}
          {{- if ne $.Site.Params.tagcloud.style  "simple"  -}}
            {{- warnf " $.Site.Params.tagCloud.style has current value of %q. Current supported values are 'button' or 'simple'. Defaulting to 'simple'. " $.Site.Params.tagcloud.style  -}}
          {{- end -}}
          <a href="{{ "/tags/" | relURL }}{{ $name | urlize }}" 
          class="tagcloud-item" style="font-size: {{ $currentFontSize }}rem;">
          {{ $name }}<sup>{{ $tagCount }}</sup>
          </a>
        {{- end -}}
      {{- end -}}
    {{- end -}}
  {{- end -}}
</div>

Natrium Theme
This one will create a tag-cloud using incrementally increasing font sizes for more frequent tags.
Simple Tag Cloud
This one is simpler, it’ll just gather all tags, all with the same font-size.

I’ve changed the code a bit.

I added the following site parameters:

site.params.tagCloud.style:  'button'
site.params.tagCloud.largestFontSize: 1.75
site.params.tagCloud.smallestFontSize: 0.25
site.params.tagCloud.minimumMatches: 1

and can now dynamically control the style, size, and match counts…. more on this later.