Table of Contents for your Hugo pages
Table of contents
Adding a table of contents, written as TOC from now on, is an important & useful way to aid your readers’ navigation in your content on a single page. A TOC usually consist of links that point directly the headings in your content that you’re already using to break up your content.
There are a lot of automated ways to implement a TOC in Markdown & thankfully Hugo handles this for us with a small configuration change & a page method you use in your template files.
tl;dr
I cover a lot of stuff here that’s specific to my Hugo project
. A lot of the customization I’ve done is inspired by the official documentation you can find online. I’ll link to the documentation that served as the technical inspiration for this post so you can learn how to do this on your own.
Getting Started
As I mentioned before, leveraging Hugo makes this super easy. There are some
configuration options you’ll need to set first in your hugo.toml
file.
These properties allow you to set what the headings start
& end
levels are
for your custom TOC. I recommend using values of 2
& 6
respectively which
covers the whole range of headings that I like to use in my writing since the
title of the content is in a <h1/>
tag.
Once that’s set, you’ll be able to use the PAGE.TableOfContents
method in your
layout HTML templates to choose where the TOC will render. Here’s an example
for the default single.html
layout file using the method highlighted below.
➡️ Here’s the official documentation for the TableOfContents method
With the above HTML, the TOC will render above the content for your page. You can also place any markup you’d like around the method call to further markup & style Hugo’s markup for a TOC.
About Hugo’s default markup
The HTML for this is in the Hugo documentation linked above. It is similar to the following HTML. I’ve added some comments to further explain some parts.
Designing your own TOC
While you style this markup, you should also consider wrapping the generated TOC
in some kind extra markup that makes sense for your content’s design. For
instance, I like to use the <details/>
markup to handle wrap my TOC content so
that the links are hidden initially. There’s an example at the top of this post.
The markup for this is straight-forward & doesn’t modify the markup coming in
from Hugo. I wrap my TOC inside of the necessary markup while also adding
some extra logic in Go around when it should display or not. If I write
something that’s shorter than 400 words or if I set toc = false
in the front
matter of a post, my TOC doesn’t appear.
Here’s the HTML markup I have for what I described above.
Note the ne
or not equals checking for the .Page.Params.toc
to not be
equal to false
. This means that you can disable the TOC but not have to set
the parameter on all your pages. This is most helpful when you’ve got content
already & don’t want to modify front matter on old files.
Below are the styles to replace the <summary/>
details marker across browsers
with an icon from my mono-space font & some minor positional styles for the
<ul/>
markup coming from the internal Hugo TOC markup. I don’t bother
modifying the <li/>
& <a/>
markup here since I handle that by extending
the styles in my configuration of Tailwind’s typography plugin
in
the tailwind.config.js
file.
Since the TOC I display is always within a prose
parent Tailwind class, I
use Tailwind’s typography plugin to extend the default CSS styles for
interacting with the <summary/>
markup & how it animates on open & close as
well.
While this does mean that my styles for TOC are defined across different files, this works for me as the TOC inherits the styles from the plugin I’m using along with specific styles that I setup up as a component within Tailwind.
Moving your custom TOC to a partial template
While having it in the single.html
layout file is okay, we can turn this into
a partial template that we can reuse across other layout files. This is
convenient when you want to same kind of TOC but for different kinds of content
that have their own single.html
file.
Using shortcodes templates
Now if you’d like to get your TOC to appear inside your content rather than
outside of it, then using Hugo’s shortcodes are going to be how you achieve
it. Go & create a new HTML file named toc.html
in your project’s
layouts/shortcodes/
directory. You may need to create the shortcodes/
directory first.
With that you will be able to add a TOC to any content by using either of the
the syntaxes {{< toc >}}
or {{% toc %}}
to render the shortcode
above. Make sure you add any HTML markup you’d like to further customize the
TOC inside the content. This might be different than what is inside your
toc.html
partial since it’s inside your content.
I’m actually using it on this page to render this post’s TOC below inside of the
Markdown content. It’s got a different style & markup than the <details/>
design. And with the ability to turn off the single.html
TOC via front matter,
I can leverage this new TOC via shortcode wherever within my content if I want
to bring attention to the topics getting covered in the post.
Thanks for reading this far. I hope this breakdown of how I created the various TOC for my Hugo site inspires you to add one or more to yours as well.
This post was written by a human & not by artificial intelligence (AI) tools. I don't have anything against AI but I am interested in differenciating content created by people versus machines. To find out more about the Not by AI badge, please click it.
If you enjoyed this post, please explore other posts by the topics listed below.
Data classes in Python