How can I use Section headings to create a table of contents? | Community
Skip to main content

How can I use Section headings to create a table of contents?

  • September 21, 2020
  • 8 replies
  • 0 views

seoj

I use section headings a lot, how can I use them for my table of contents? The link only has URL or headings options.

8 replies

  • September 23, 2020

Hi @seoj

Depending on what you mean by "section headings", there are a number of ways to achieve this.

In the example below I describe a code-based solution that will automatically generate a table of contents for your articles without you having to alter the article content.  It uses headings within an article to create the list:

document.addEventListener('DOMContentLoaded', function() {
var articleBody = document.querySelector('.article-body');
var tableOfContents = document.getElementById('toc');

// Do nothing if the article body or table of contents element doesn't exist
if (!articleBody || !tableOfContents) {
return;
}

// Get article content headings
var headingSelector = 'h1, h2, h3, h4, h5, h6'
var headings = Array.prototype.slice.call(articleBody.querySelectorAll(headingSelector));

// Add an ID to each heading if they don't already have one
Array.prototype.forEach.call(headings, function(heading, index) {
heading.id = heading.id || 'heading-' + index;
});

// Only include headings with an ID
headings = headings.filter(function(heading) {
return heading.id
});

// Do nothing if there are fewer than 2 headings with IDs
if (headings.length < 2) {
return;
}

// Render the list
var html = headings.map(function(heading) {
return (
'<li>' +
'<a href="#' + heading.id + '">' +
heading.childNodes[0].textContent +
'</a>' +
'</li>'
);
}).join('');

html = '<ul>' + html + '</ul>';
tableOfContents.insertAdjacentHTML('afterbegin', html);
});

It's self contained and so can be copy-pasted above or below the code that you currently have in your script.js file.

What it does:

  1. Finds all headings (<h1> - <h6>) within the content
  2. Adds a dynamic ID to headings that don’t already have an ID
  3. Generates and displays a simple list of headings

To have it display on all pages with two or more headings, insert a <div> with ID of "toc" into your article page template.  For example:

<div class="article-body">
<div id="toc"></div>
{{article.body}}
</div>

When a visitor clicks on a heading link, the page is scrolled to that heading/section in the page.

By changing the list markup (<ul> and <li> elements) and adding custom CSS, your can make the list look however you like.

The code can also be used on other pages (e.g., category page) and reference other “section” types, not just headings, by altering the articleBody (i.e., parent element) and headingSelector variables.

This example is a much simpler version of the custom Table of Content plugin that we’ve created as part of our theme customisation framework especially for this type of use case.

Hope that helps!

Jim

Zenplates - Custom themes, plugins and apps for Zendesk


seoj
  • Author
  • September 26, 2020

Thanks, Jim. Let me see if I can implement this. I don't have complete access to guide and also not much familiar with codes and themes. 

this is what I mean by section heading <span class="section-heading">Introduction</span>

 


Connor15
  • January 8, 2021

How do you recommend adding a title to the list? I want it to say something like "in this section"

 


  • January 8, 2021

Hey @Connor Mathena

Assuming you'd like the title to only be displayed when the list is displayed (which only happens when there are two or more heading with IDs in the article content), I'd recommend adding your title to the second to last line.  For example:

html = '<h3>In this section</h3><ul>' + html + '</ul>';

You can of course add any other HTML that you like there and style it all using custom CSS in your theme's style.css file.

Cheers,

Jim


Connor15
  • January 8, 2021

Thank you so much Jim!

 


Nicole17
  • January 10, 2021

Thanks for jumping in with your answers, Jim! 


  • January 11, 2021

Is there an easy way to nest these based on h1,h2,h3

 

Something like:

<ul>
<li>Coffee (H1)</li>
<li>Tea (H1)
<ul>
<li>Black tea (h2)</li>
<li>Green tea (h2)</li>
</ul>
</li>
<li>Milk (H1)</li>
</ul>

  • August 31, 2021

@Phil Sampson I was trying to do the same thing and got the answer here. The only change I made was using <ol> tags instead of <ul> tags:

https://support.zendesk.com/hc/en-us/community/posts/1500000064241/comments/4406611671578