Header anchors in Hugo

Pipeline

One of the most popular things you can see on almost all blogs is anchors. Anchors are the icon or text link to something in the post. Header links are by far the most popular use case for anchors.

I've implemented this feature for the blog and want to share knowledge. It's a pretty easy thing to do with a combination of out-of-box Hugo features, but haven't seen this combination described anywhere.

Reference

Hugo by default has the option to reference headers.

If you write this markdown.

# First
## Second
### Third

It got translated into this html code by default.

<h1 id="first">First</h1>
<h2 id="second">Second</h2>
<h3 id="third">Third</h3>

Note the id attribute on header tags. If you add #id to the end of post URL, browser will redirect you directly to this header tag. For my example adding #first to URL will link to <h1 id="first">First</h1> tag.

This feature is described here on Hugo documentation.

So everything we need to do is to change the markup to have this link opened.

Markup

Hugo has a nice feature which is called Markdown Render Hooks.

Basically, you can override how some features are rendered from markdown text. We need to override Heading.

For this, we should add layouts/_default/_markup/render-heading.html to the blog or to your custom theme directory. My template below.

<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }}
{{- if and (ge .Level 1) (le .Level 6) }}{{" " -}}
<a class="anchor" href="#{{ .Anchor | safeURL }}">
    <i class="fas fa-hashtag"></i>
</a>
{{- end -}}
</h{{ .Level }}>

Let's describe it more detailed. It's a template which will be used by <hN> tags, where N is 1 to 6, you can see if statement with this check. I created <a> tag referencing an anchor variable and used and icon fas fa-hashtag from Font Awesome. You can use a text link instead of icon or anything you want here.

Result

So that's all I had to do to implement header anchors for the Hugo blog. You can see the "demo" on this site. Look at the sharp icon near every header inside of any post.

For more specific details of my Hugo setup you may want to check out a post about blog deployment pipeline.