How to Create a Table of Contents for Your Essay

by SkillAiNest

When you create an article, such as a blog post for freeCodeCamp, Hashnode, Medium, or DEV.to, you can help guide the reader by creating one. Table of Contents (ToC). In this article, I’ll explain how to build using JavaScript and browser dev tools. The article will explain how to use Google Chrome Dev Tools. But the same can be applied to any modern browser.

The process in this article needs to be done once on each platform. Once you have the code, you can apply it every time you create a ToC. Note that if the platform changes, you may need to adjust the script.

Table of Contents

Browser Dev Tools

DevTools is a browser extension that allows you to inspect and manipulate the DOMDocument object model), which is a representation of HTML that the browser keeps in memory in the form of a tree. It also provides access to the JavaScript console, where you can write short code snippets to test an object. It has many more features, but we will only use these two.

To open Dev Tools (in Google Chrome), you can press F12 or right-click on the page with your mouse and click Inspect.

A browser window split in half. On the right is an example of a laptop with a FreeCodeCamp article there is a browser DevTools with a DOM Tree and CSS panel.

Above is a screenshot of DevTools with a preview of this article. On the right, you can see a selected one. h1 HTML tag (title) and CSS are applied to this tag. The tree structure you see is the DOM.

💡

When creating a ToC for Free Code Camp, You should open the preview in a new tab.

JavaScript console

We’ll need to access the JavaScript console. To open the console in Google Chrome, you can use F12, right-click on the page and select Inspect from the context menu, or use the shortcut CTRL+SHIFT+C (Windows, Linux) or CMD+OPTION+C (Mac).

In Chrome DevTools, you can select the Console tab at the top of DevTools. But this will hide the DOM tree. Better to open the bottom drawer. You need to click on the 3 dots in the upper right corner and select “Show Console Drawer”.

A screenshot of a menu that docks dev tools to the right, left, bottom, or standalone window.

The dev tools will look like this:

Screenshot of Browser Dev Tools showing the DOM Tree, CSS Panel, and Console Drawer.

💡

You can ignore any errors or warnings in the console. You can click this icon 🚫 to the left of the drawer, and it will clear the console.

A console is a so-called. read-evil-print-loop. A classic interface, where you type some commands, JavaScript code here, and when you press enter, the code is executed in the context of the page DevTools is on.

Screenshot showing the browser alert popup in the DevTools console and the JavaScript code that opens the alert.

Above, you can see the page alert executed from the console.

Understanding the structure of the DOM

The first step in creating a ToC is to inspect the DOM and look for headers. They usually are. H1…H6 H1 tags are often the page title. In an ideal world, it would last forever.

In my case, the header looks like this:


The article only contains H2 tags, but later in the article, I will also explain how to create a nested ToC.

💡

Your headers must have an “id” attribute. It may look different, for example, on a different element, but it must be in the DOM. Later in the article, I’ll cover some different structures and how to deal with them.

Now with DevTools, we can write code that will search for each header:

document.querySelectorAll('h2(id), h3(id), main h4(id)');

In the case of my article on FreecodeCamp, it returned this output:

NodeList(5) (h2#heading-dev-tools, h2#heading-javascript-console, h2#heading-understanding-the-dom-structure, h2#trending-guides.col-header, h2#mobile-app.col-header)

First, this is a NodeList that we need to convert to an Array. Second, in addition to our headers that we have so far, we also have two headers that are part of the website and not the main content. So we need to find the only element that is the parent of the headers we need.

You can right-click on the white page containing the article and select Inspect the element.. In our case, it found an element

. So we can rewrite our selector like this:

document.querySelectorAll('main h2(id), main h3(id), main h4(id)');

And now it returns our headers and nothing more.

💡

gave (id) There is actually no need for an attribute selector here. At least not on the freecode camp.

How to Create a ToC in Markdown

Many blogging platforms support Markdown, so this will be the first thing we’ll build.

First, we’ll convert the node list to an array. We can use Diffusion operator:

(...document.querySelectorAll('main h2(id), main h3(id), main h4(id)'));

Then we can map to the array and create markdown links that point to the given header.

const headers = (...document.querySelectorAll('main h2(id), main h3(id), main h4(id)'));

headers.map(function(node) {
    // H2 header should have 0 indent
    const level = parseInt(node.nodeName.replace('H', '')) - 2;
    const hash = node.getAttribute('id');
    const indent=" ".repeat(level * 2);
    return `\({indent}* (\){node.innerText})(#${hash})`;
});

The output looks like this:

(4) ('* (Dev Tools)(#heading-dev-tools)', '* (JavaScript Console)(#heading-javascript-console)', '* (Understanding the DOM Structure)(#heading-understanding-the-dom-structure)', '* (What to do if I don’t have headers?)(#heading-what-to-do-if-i-dont-have-headers)')

To get the text, we can join the array with a newline character and use console.log to display the output. If we don’t use console.logit will show a string next to it. \n letters

const headers = (...document.querySelectorAll('main h2(id), main h3(id), main h4(id)'));

console.log(headers.map(function(node) {
    // H2 header should have 0 indent
    const level = parseInt(node.nodeName.replace('H', '')) - 2;
    const hash = node.getAttribute('id');
    const indent=" ".repeat(level * 2);
    return `\({indent}* (\){node.innerText})(#${hash})`;
}).join('\n'));

The output of this article will look like this:

* (Dev Tools)(#heading-dev-tools)
* (JavaScript Console)(#heading-javascript-console)
* (Understanding the DOM Structure)(#heading-understanding-the-dom-structure)
* (Creating TOC in Markdown)(#heading-creating-toc-in-markdown)
  * (This is fake header)(#heading-this-is-fake-header)

I created a fake subheader. Platforms, even when not supporting Markdown when writing articles, often support Markdown when copying and pasting. The ToC at the top of the article was created by copying and pasting the generated Markdown with the last JavaScript snippet.

How to create HTML ToC

If your platform doesn’t support Markdown (like Medium), you can generate HTML, preview that HTML, and copy the output to the clipboard. Pasting it into the editor for the platform you’re using should retain the formatting.

💡

On the medium, the material is contained within a.

element, so the selector must be updated.

To convert Markdown to HTML, you can use any online tool, but you’ll see it in bits and pieces. It will be faster after building the code.

const headers = (...document.querySelectorAll('main h2(id), main h3(id), main h4(id)'))

function indent(state) {
    return ' '.repeat((state.level - 1) * 2);
}

function closeUlTags(state, targetLevel) {
    while (state.level > targetLevel) {
        state.level--;
        state.lines.push(`${indent(state)}`);
    }
}

function openUlTags(state, targetLevel) {
    while (state.level < targetLevel) {
        state.lines.push(`${indent(state)}
    `); state.level++; } } const result = headers.reduce((state, node) => { const level = parseInt(node.nodeName.replace('H', '')); closeUlTags(state, level); openUlTags(state, level); const hash = node.getAttribute('id'); state.lines.push(`\({indent(state)}
  • ${node.innerText}
  • `); return state; }, { lines: (), level: 1 }); closeUlTags(result, 1); console.log(result.lines.join('\n'));

This is the output of the code in this article:


I’ve added some headers at the end, so you can see that this will work for any level of nested headers. Note that we also have ToC as the first element in the list.

💡

Note that the above HTML code includes a link to the table of contents. This happens if you run the script again after adding the TOC. You can remove it by hand. If you want to improve the code, you can add filters.

Copy the HTML code for the editor.

The most so called WYSIWYG The editors are using HTML, and you should be able to copy and paste the output of the HTML code with formatting into that editor. The easiest is to save it to a file, open that file, and select the text:

A screenshot of a browser window with an open file. The page in the browser displays a table of contents where all text is highlighted by selection.

What if I don’t have headers?

You need to find anything that can be targeted with CSS. If they are p Tags with a specific class (like headers), you can use p.header instead of h2.

How to create a table of contents for DEV.to

If your DOM structure is different, you can use different DOM methods to extract the element you need. For example, on DEV.to, the headers look like this:

Overview

So the selector should be fair. main h2. But when you execute this code:

(...document.querySelectorAll('main h2, main h3, main h4'));

You’ll notice that there are more headers than document content. Fortunately, we can use a new selector in CSS. :has(). A final selector for a header might look like this: main h2:has(a(name)).

Here is the complete code:

const selector="main h2:has(a(name)), main h3:has(a(name)), main h4:has(a(name))";
const headers = (...document.querySelectorAll(selector));

console.log(headers.map(function(node) {
    // H2 header should have 0 indent
    const level = parseInt(node.nodeName.replace('H', '')) - 2;
    // this is how you get the hash
    // you can also access href attribute and remove # from the output string
    const hash = node.querySelector('a').getAttribute('name');
    const indent=" ".repeat(level);
    return `\({indent}* (\){node.innerText})(#${hash})`;
}).join('\n'));

The result

Creating a table of contents can help your readers digest your article. Since most people don’t read the entire article, they only scan for what they need. You can also find many articles about its impact on SEO. So if the article is long, it is always worth adding it.

And as you can see, creating a ToC with a little knowledge of web development is not that difficult.

If you like this article you may want to follow me on social media 🙁Twitter/X, GitHuband/or LinkedIn). You can also check mine. Personal website And mine New blog.

You may also like

Leave a Comment

At Skillainest, we believe the future belongs to those who embrace AI, upgrade their skills, and stay ahead of the curve.

Get latest news

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

@2025 Skillainest.Designed and Developed by Pro