How To Use Linked Headers in Hugo

- 3 minutes read

If you’re looking to use linked headers in Hugo, or customize some other aspect of the headers outputted by your Markdown, you’ve come to the right place.

Link to this section Render hooks

First, you’ll need to create what Hugo calls a “render hook”.

Render hooks let you override default Markdown rendering.

In the case of overriding the header tags rendered by your Markdown files, you must create the following file in your site’s root: _default/_markup/render-heading.html.

Link to this section Building your linked header template

Once you’re in your render-heading.html file, you can get started with the following code:

<h{{ .Level }}>
    {{ .Text | safeHTML }}
</h{{ .Level }}>

This will turn the following Markdown:

## Test
### Test

Into the following HTML:

<h2>Test</h2>
<h3>Test</h3>

Great. Now, we’ll add an ID to our headers so that we can link directly to a section of the page, like in the following link: https://natclark.com/tutorials/hugo-linked-headers/#render-hooks

<h{{ .Level }} id="{{ .Anchor | safeURL }}">
    {{ .Text | safeHTML }}
</h{{ .Level }}>

On this page, if you’re using a mouse, you can hover over one of the headers to make a little link icon pop up. Try it out on the header just above this line!

If you click it, the page and URL will automatically navigate to the ID of the clicked header. This way, you can easily share a link to that specific part of the page.

If you’d like to do something like that in your linked header template, you can paste the following into your render-heading.html file:

<h{{ .Level }} id="{{ .Anchor | safeURL }}">
    <a class="hash-link nohover" href="#{{ .Anchor | safeURL }}">
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="red" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <title>Link to this section</title>
            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
            <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
        </svg>
    </a>&nbsp;{{ .Text | safeHTML }}
</h{{ .Level }}>

Lastly, let’s add some CSS to position the .hash-link selector.

.hash-link {
    -webkit-transform: translateX(-100%);
    color: red;
    left: 0;
    opacity: 0;
    padding: 0 5px;
    position: absolute;
    transform: translateX(-100%);
    transition: opacity .1s ease-in;
    will-change: transform, opacity;
}

And that’s the trusty render hook template I use for my linked headers. You’re more than welcome to use it without permission or attribution.

Link to this section Conclusion

I’ve recently fully customized this blog using Hugo, so I’ve been writing about the weird parts I’ve had to figure out, while they’re still fresh on my mind.

Figuring out and customizing all my render hooks took a little while. But I hope this guide saved you some time!