How to Add Anchor Links to Headers in Hugo
The great thing about adding anchor links to headers in Hugo is that Hugo already adds an id
to the headers on every page. Our job is simply to link to that id
.
First, we need to know where our content is being displayed.
We’ll do that by searching for usage of .Content
.
Normally, we’ll find it in single.html
.
{{ .Content }}
1. Using Hugo templating
We can replace the above {{ .Content }}
with the following:
{{- with .Content -}}
{{ . | replaceRE "(<h[2-4] id=\"([^\"]+)\".+)(</h[2-4]+>)" `${1}<a href="#${2}" class="hanchor" ariaLabel="Anchor">#</a>${3}`| safeHTML }}
{{- end -}}
The regex simply groups header tag elements (e.g. <h2>
, <h3>
, <h4>
) and replaces it with the same elements including an anchor tag at the end of the it.
We’ll style the
hanchor
class below.
We can target specific header tags by modifying h[2-4]
to be h2
or h[3-5]
or whatever we want.
Similarly, we can modify the actual anchor text. Lots of people prefer the link icon 🔗 over the hash symbol #
.
2. Using JavaScript
We can also use JavaScript to create the anchor link.
After the DOM has been loaded, we want to target all headers tags in our content.
In my Hugo site, my
{{ .Content }}
is wrapped in adiv
withclass=article-post
, so I’ll specifically target headers within thatdiv
(e.g..article-post h2[id]
). Be sure to change this depending on your Hugo layout.
document.addEventListener("DOMContentLoaded", function (event) {
const headers = document.querySelectorAll(
'.article-post h2[id], .article-post h3[id], .article-post h4[id]')
if (headers) headers.forEach(addAnchor)
});
function addAnchor(element) {
element.insertAdjacentHTML(
'beforeend',
`<a href="#${element.id}" class="hanchor" ariaLabel="Anchor">#</a>`
);
}
Styling the anchor
Here are my recommended styles for quality anchor text.
.hanchor {
visibility: hidden;
color: silver;
font-size: 100%;
transition: 0.2s;
padding-left: 8px;
font-weight: 600;
}
h2:hover a, h3:hover a, h4:hover a {
visibility: visible;
text-decoration: none;
}