We all know table of content is very important for the convenience of the reader experience. So that today I will show you how you can add table of contents like this:

The red arrow represents the end result that we want to get

On the ghost.org website there is a really good tutorial about how to do this:

Tutorial: How to add a table of contents to your Ghost site
In this tutorial we’ll show you how to automatically generate a table of contents from the section headings in your content.

You may wonder: why should I write again about the same topic? Well, I try to use the examples illustrate on this website, but I think there are some important information that is missing. So I want to add them in here, in order to make easier for you to modify the theme by yourself.

Now let's begin!


Download the theme

You can go to your ghost admin, then choose theme, you could see something like this:

The number represents the order of the clicking

Then you can download your theme by pressing the Download button, then you can open it by using any editor (I would recommend vs code, which is really powerful and beautiful).

After open in vs code, you will see something like this:

The three arrows show all three files that we need to modify

Now let's modify these three files: screen.css, default.hbs, post.hbs.


Modification of the file

If you want to understand how this theme works, you need basic knowledge on HTML, CSS and some javascript, which are very simple to learn, I will explain to you along the way, but it will be better if you could learn the basics (unless you are already an expert, which you do not need my advice).

post.hbs

You can find {{content}} in the file, and then replace it with the following code:

<section class="gh-content gh-canvas">
    <div class="post-full-content">
        <aside class="toc-container">
            <div class="toc"></div>
        </aside>
        <div class="post-content">
            {{content}}
        </div>
    </div>
</section>

Where gh-content and gh-canvas are the container for the article, post-full-content is the content of the article, and the toc-container and toc are the table of contents. Now we want to modify their css. But before we do that, let's add a package to the header and footer file.

default.hbs

In the <head> section, you can add these two lines above {{ghost_head}}:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.12.2/tocbot.css">
<link rel="stylesheet" type="text/css" href="{{asset "css/screen.css"}}" />

Also you need to add the following code above {{ghost_foot}}

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.12.2/tocbot.min.js"></script>
<script>
    tocbot.init({
        tocSelector: '.toc',
        contentSelector: '.post-content',
        hasInnerContainers: true
    });
</script>
{{{block "scripts"}}}

Now we can modify the css file, which is the hardest in this process, because there are many things that we need to consider.

screen.css

If you go to the end of screen.css, then you will see this:

In the end of screen.css file, which means you can add your own css

Then you can add the following css codes:

/* Offset headings from fixed header */
.post-content h2::before,
.post-content h3::before {
    display: block;
    content: " ";
    height: 84px;
    margin-top: -84px;
    visibility: hidden;
}

/* Adjust content wrapper */
.post-content {
    display: block;
}

/* Adjustments to wide and full width cards */
.kg-gallery-card,
.kg-width-wide,
.kg-width-full {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.kg-gallery-card > *,
.kg-width-wide > *,
.kg-width-full > *,
figure.kg-width-full img {
    margin-left: -50vw;
    margin-right: -50vw;
}

/*.post-full-content pre {
    max-width: 0;
}*/

@media screen and (min-width: 800px){
    .post-content h2,
    .post-content h3 {
        outline: none;
    }
    body {
        overflow: visible;
    }
    .post-full-content {
        display: grid;
        grid-template-columns: 1fr 0.5fr;
        padding: 0 0 6vw;
        margin: 0;
    }
    .toc-container {
        order: 1;
    }
    .toc-container .toc {
        grid-column: main-end/full-end;
        position: sticky;
        top: 70px;
        min-width: 260px;
        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
        Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif;
        font-size: 1.6rem;
        line-height: 1.6em;
        padding: 0 0.8em;
    }
    .is-active-link::before {
        background-color: #3eb0ef;
    }
    ol.toc-list {
        margin: 0;
    }
}

Also we need to modify the settings for the gh-canvas, in order to treat mobile and desktop differently (iPad and other similar devices are more and more like computer, so we will treat them the same as desktop)

.gh-canvas > * {
    grid-column: main-start / main-end;
}

@media screen and (min-width: 800px){
    .gh-canvas > * {
        grid-column: wide-start / wide-end;
    }
}

If you complete all the procedure above, then you will see the table of content shows on the right of your screen, isn't that beautiful? It is extremely useful when you have really long blog post (which is very commin on this blog).

Hope you will enjoy this blog. Subscribe if you want.

Take care, bye!

Yours,

Zhengda