Add a Table of Contents to Drupal using TOC.js jQuery Plugin

Published Jul 5, 2024
Updated Jul 5, 2024
By Simon
Table of contents

I chose the Toc.js module because I wanted a quick option where I could have a table of contents at the top of the article, like the one above. It showed this on the Drupal project page. The only other Drupal 10 TOC module that may have worked was the TOC filter, but I like the idea of a checkbox to enable it instead of needing to use a filter in a text area.

What is filter? A filter is a short-code or small snippet of code, usually wrapped in square brackets like this [toc], you can add to a text area, and when the page is rendered, the filter will be replaced by HTML.

Toc.js also has the option to create a TOC block and place it in a region, like the other TOC options available. I haven't tried this yet, but as I refine the content type of this site and move the TOC to a fixed sidebar, I will definitely try it and add notes below.

Since setting it up, I have experimented with the module's many features and uncovered a few bugs or issues. In this article I will be covering all these, but for a quick TOC at the top on an article it works well. 

Installing Toc.js

You can install Toc.js like any other module.

If you use composer to manage your site, then you can use composer to require the TOC.js library.

If you don't use composer, you will have to manually download the TOC.js library and place it in the correct directory.

For both methods of installing the TOC.js please check the project page on Drupal.org.

Once TOC.js is downloaded, you can then install it on the extend page. There is a second module called Toc.js per node that comes with the main module. Depending on your needs, you can install it at the same time as the main module or at a later time. Please read the note below on this, as it seems there are minor differences on the default configuration depending on when Toc.js per node is installed.

Hint: Make sure permission are correct. As an admin user it will work, but if you have other user roles you will need to enable them.

Configuration

Once you have installed the module, you can enable it for any content type you like. This is easily done on the edit content type page. For the article content type, the path is as follows:

Manage > Structure > Content types > Article
/admin/structure/types/manage/article

Basic Table of Content Setting

  • Click the Enable Table of Content Checkbox
Image
enable table of content checkbox on content type configuration page

After you have enabled it, there are many settings. To keep things simple; a TOC at the top of the content, make sure the settings outlined below are set. This is the best setup for the module if you don't have time to make a lot of adjustments and add custom code.

  • Container change it to I targeted the correct container, I am using .field--name-body
    By default, it targets the .node container, so the table of contents will include everything in the node, this includes the comments h2 heading. This was simple to change by adding the .field--name-body class on the settings page.
  • Disable Smooth Scroll
    I have added rules to the HTML selector in the theme CSS instead. 
    If you want to use this, you may need to uncheck and re-check to get access to the ScrollTo offset.

    Image
    smooth scroll checked with scrollTo offset set to 210px

    Here is the code that I had already added to the HTML element in my CSS to get the same behaviour.

    scroll-padding-top: 210px;
    scroll-behavior: smooth;

    The scroll-padding-top is used to make sure that the element you scroll to is 210px below the top of the window. Useful for when you have a fixed navigation. 
    The smooth value of the scroll-behavior property enables a nice scroll to the element, instead of a quick jump. 

That's it for the main settings to make this work at the top of your content.

Add it to your display

Visit the manage display tab and drag the TOC field from disable to the location you want it. 

Image
drupal content type manage display tab
The manage display tab showing the Toc above the body field for the Default display

Adding CSS to your theme

How you style things is up to you; below is what I did with some code for you to use.

  1. I added some CSS to highlight the headings that are scrolled to. I did this by using the :target pseudo class on the spans that are added by the module. Go on, click on the link to see the heading highlight.
  2. Styled the table of contents.
    1. Bolded the h2 to show hierarchy.
    2. I added indents on the h3 index items and used a different list-style to show hierarchy.
    3. Added a box around it with a border.
       
.toc-js {
  background: #e4e0e057;
  padding: 1rem; /* make left a little more */
  width: fit-content;
  min-width: 500px;
  margin-top: 2rem;
  border: 1px solid #cbcbcb;
}
.toc-js ul {
  padding-left: 0;
}
.toc-js a {
  color: var(--body-color);
}
.toc-title {
  font-size: 1.2rem;
}
.toc-h2 {
  font-weight: 600;
  margin-left: 1rem;
}
.toc-h3 {
  margin-left: 2rem;
  list-style: circle;
}

 

So, that is it. For a simple TOC at the top of your content, this is a great module. If you want to use some of the other features, be warned, they come with caveats. Read on to find out more.

Other Features of the Toc.js Module

After installing and configuring the Toc.js module, I found a few intricacies and bugs related to things other than the most simple implementation outlined above. I am using Drupal 10, and I am unsure if they are Drupal-10-specific or somehow related to my theme. If you use a different version of Drupal, then you will have to test it for yourself. I don't think they are related to my theme, so if you have set it without these issues, please let me know. 

Toc.js per node

If you want control over which content the TOC is displayed on, you need to enable the extra module, Toc.js per node. You do this on the extend page, and then a new setting appears on the content types settings. This is an excellent feature, especially when adding to an existing site. 

Image
enable toc per node

Once you have installed and enabled it for your content type, an option will be available on all content.

Highlight on scroll highlights the current active heading 

The highlight on scroll doesn't work as I would expect. It adds the highlight or active class to the TOC. Great if the TOC scrolls with the content as the current heading is highlighted. 

Back-to-top link feature

This adds a back-to-top link next to each heading. It's a little buggy in that the top offset is set to the heading you clicked on. This means that sometimes the TOC's top is cut off. 

Sticky, stick index to top

Back-to-top becomes broken if you enable the stick index to top. I believe this is because the back-to-top is tied to the index and since the index is stuck to the top then the index is at the top and has nowhere to scroll to. I am sure this could be fixed, or maybe just don't use it together and implement a separate scroll to top.

If you do use the sticky to top in the content type then you will also need to think about placement and adding a background.

Knowing these bugs or issues you can make this work, however.

Logged-in Users

One other issue, that isn't such an issue, is that logged-in users seem to get multiple heading spans and back-to-top links added. The number is somewhat random but related to the amount of headings. So if you have users that are logged in while using the site, and maybe have edit permissions for the content, you will need to fix that. In my case, I am the only user and can live with it for now. 

If you enable any of these extra features, you'll need to style the elements, namely the Index and back-to-top buttons.

Summary

This is a good TOC solution that uses jQuery and a library. All you need to do is composer require, enable, configure it and then style it.

If you want to use a vanilla JS solution and have a sidebar region, then Tocbot may be the way to go. I will be looking at Tocbot when the time comes.

If you have got this far, you will also know the few issues that may arise if you go past the basic setup. 

Finally, I have also provided some CSS to help style your table of contents and headings that are scrolled to. 

I hope this has been useful to decide on whether to use Toc.js module on your site. If you need a table of contents at the top of your article, then I think it is a great solution. Thanks for reading and be sure to sign up for the newsletter below for more great content on Drupal, front-end development and design.