How to Add Tocbot (Table of Contents) to your Hugo Site
I’ve found Tocbot to be the cleanest table of contents (TOC) generator. It highlights and bolds as you scroll, uses vanilla JavaScript (avoids dependencies), works on all modern browsers, and is incredibly configurable.
If you want to see it in action, check out the Tocbot website.
On many of the projects I’ve worked on, I’ve found myself using Hugo along with Tocbot, so I want to demonstrate how I get this up and running.
Download Tocbot
Let’s download the latest release of Tocbot from Github.
We’ll need to unzip the folder to access the files.
We only really need to focus on the /dist
folder in the root directory.
Inside /dist
, there are three files we want:
styles.css
tocbot.css
tocbot.min.js
Let’s copy these guys and head over to our Hugo project.
Add Tocbot Files to Our Hugo Project
In your file system, navigate to where all your css
and js
assets are.
They’ll most likely be in your /static
or /assets
directory, which can be configured in your config.toml
through the staticDir
and assetDir
keys.
Paste the single .js
file and the two .css
files into their respective folders.
Link to the Tocbot CSS Files
Find the .html
file that contains the <head>
tag (it’s very likely head.html
).
We’ll want to link to these .css
files in our <head>
tag.
<!-- Tocbot Styles -->
<link rel="stylesheet" href="[css_dir_path]/tocbot.css">
<link rel="stylesheet" href="[css_dir_path]/styles.css">
One random caveat: Tocbot will not properly track scroll height (and therefore will not highlight the active heading) if
overflow-x: hidden
is set for the page’sbody
tag.
Specify Location of TOC
I placed my TOC in my sidebar.html
.
Unfortunately, this may not be available to you depending on your theme and layout.
Many people do place it in their single.html
file.
<!--Tocbot TOC Placeholder -->
<div class="js-toc"></div>
Your class name does not need to be js-toc
.
Specify Location of Content
Your Tocbot will dynamically generate your TOC by searching for header tags (<h1>
, <h2>
, etc.) in your content.
But it doesn’t know where the content is, so that’s why we need our content to be wrapped inside a <div>
with class js-toc-content
.
This might mean you’re creating a new <div>
around your content or simply adding a new class to an already existing <div>
(this latter option makes more sense to me).
Search all your .html
files for .Content
, since this is where Hugo will generate the posts from your content
folder.
It is likely inside single.html
, which is where I put this code snippet.
<!-- Post Content -->
<div class="article-post js-toc-content">
{{ .Content }}
</div>
Again, the class name does not need to be js-toc-content
.
Initialize Tocbot Scripts
The first thing we want to do is add the tocbot.min.js
file we downloaded earlier to our Hugo project.
We generally have two options:
- Add Tocbot to every page on our site: add
<script>
tag tobaseof.html
- Add Tocbot only to article pages: add
<script>
tag tosingle.html
<script src="[js_dir_path]/tocbot.min.js"></script>
Next, we want to initialize Tocbot directly after the <script>
tag above.
We can use tocbot.init()
to do this. We need to specify where to render the TOC and where the content is.
<!-- tocbot options -->
<script type="text/javascript">
tocbot.init({
// Where to render the table of contents.
tocSelector: '.js-toc',
// Where to grab the headings to build the table of contents.
contentSelector: '.js-toc-content',
// Which headings to grab inside of the contentSelector element.
headingSelector: 'h1, h2, h3'
});
</script>
If you changed either class name (.js-toc
or .js-toc-content
) in a section above, make sure you reflect that change in the initialization here.
For more ways to customize your Tocbot, be sure to check out the official Tocbot website.
Conclusion
There you have it! You should have a working TOC for your Hugo site.
This is a fairly straightforward and simple process, but it can be confusing when you’re first starting out with Hugo.
Good luck starting your site!