Host a Ghost Blog on AWS in 2023 (IV) - Create a Functional Table of Contents

Host a Ghost Blog on AWS in 2023 (IV)  - Create a Functional Table of Contents
Photo by Vincent Yuan @USA / Unsplash

A functional table of contents (TOC) is easy for users to navigate through the long article, but Ghost did not provide a nice out-of-the-box solution. This post is to show you how to build a nice table of contents like you see on the right with easy tweaks.

Besides, for those who are interested in building the blog, the prior 3 parts are the go-to reference:

Host a Ghost Blog on AWS in 2023 (Part 1) - AWS Setup
I used to share a lot of programming and data science content on the Internet along with a few friends, BulletTech is one of the websites we built to this end, and we have actually learnt a lot during peer review and discussion on those topics. This reminds me of
Part 1 - Set Up Ghost On AWS
Host a Ghost Blog on AWS in 2023 (Part 2) - Domain Setup
Following the last part of installing Ghost on AWS, the website should be up and running, but the website can only be accessed by its IP address, so in this post the tutorial of setting up the domain will be shared to show that how your website can be access
Part 2 - Domain Setup for Ghost
Host a Ghost Blog on AWS in 2023 (Part 3) - Blog Customization
Healthy food for thoughts about this beautiful life!
Part 3 - Blog Customization

1 Problem Statement

Ghost in fact introduces a simply table of contents in the official tutorial:

How to add a table of contents to your Ghost site
Let your readers know what to expect in your posts and give them quick links to navigate content quickly by adding a table of contents with the Tocbot library.
Build a Primitive Table of Contents

The TOC can be inserted into your theme, but in most cases they are not user friendly and pretty:

  • Everything is underlined
  • It is too close to the content
  • It is overlapped with meta data like author, tags
  • It is overlapped with wide or full images
Bad Example of the TOC

2 Fix

Suppose that you have followed the example shared by Ghost official document, then the default.hbs and post.hbs have been updated and the Tocbot code has been added. Please do it if you have not so that at least there is a TOC no matter how bad it is :p

Now what we need to fix is the style of the TOC by editing the code in default.hbs.

2.1 Style

Firstly, go to the default.hbs file, below CSS code is inserted above {{ghost_head}} to set proper styles.

<style>
        .gh-content {
            position: relative;
            z-index: 1;
        }

        /*-- Remove underline in the TOC text  */
        .gh-content a {
            text-decoration: none;
        }

        .gh-content img{
            position: relative;
            z-index: 2;
        }

        .gh-toc > .toc-list {
            position: relative;
            
        }

        .toc-list {
            overflow: hidden;
            list-style: none;
            left: 20%;

        }

        @media (min-width: 1300px) {
            .gh-sidebar {
                position: absolute; 
                top: 0;
                bottom: 0;
                margin-top: 4vmin;
                /* grid-column: wide-start / main-start;  Place the TOC to the left of the content */
                grid-column: main-end / wide-end ; /* Place the TOC to the right of the content */

            }
        
            .gh-toc {
                position: sticky; /* On larger screens, TOC will stay in the same spot on the page */
                top: 4vmin;

                /*-- Send the TOC to the back, in case it is overlapped with images  */
                z-index: 1; 

            }
        }

        /*-- Hide TOC on mobile devices */
        @media (max-width: 768px) {
            .gh-toc {
                display: none;
            }
        }

        .gh-toc .is-active-link::before {
            background-color: var(--ghost-accent-color); /* Defines TOC   accent color based on Accent color set in Ghost Admin */

        } 
    </style>
Style of the TOC

z-index is used to control the position of each element on the Z axis, in the above setting, images are placed on the front and the main content and TOC are behind it so that TOC does not float over wide or full images. Below snippet is added to remove the underline of text in the TOC:

/*-- Remove underline in the TOC text  */
        .gh-content a {
            text-decoration: none;
        }
Remove Text Underline

Then, grid-column: main-end / wide-end is used to put the TOC on the right, please note that if you should use grid-column: wide-start / main-start if you still expect the TOC on the left.

@media (min-width: 1300px) {
            .gh-sidebar {
                position: absolute; 
                top: 0;
                bottom: 0;
                margin-top: 4vmin;
                /* grid-column: wide-start / main-start;  Place the TOC to the left of the content */
                grid-column: main-end / wide-end ; /* Place the TOC to the right of the content */

            }
        
            .gh-toc {
                position: sticky; /* On larger screens, TOC will stay in the same spot on the page */
                top: 4vmin;

                /*-- Send the TOC to the back, in case it is overlapped with images  */
               

            }
        }
Position of TOC

Next, because the TOC is now on the right, and pretty close to the content, left: 30% is used to add margin so that it is a bit distant to the content. If your TOC is on the left, you should consider tweaking the parameter right with proper margin.

.toc-list {
            overflow: hidden;
            list-style: none;
            left: 30%;

        }
Add Margin

Also, below code is used to hide the TOC on small devices as the TOC is not able to hover side by side and so it is unnecessary.

/*-- Hide TOC on small devices */
        @media (max-width: 768px) {
            .gh-toc {
                display: none;
            }
        } 
Hide TOC on Small Devices

2.2 Function

Now go to the end of the default.hbs and below code is inserted above {{ghost_foot}}.

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.12.3/tocbot.min.js"></script>

{{! Initialize Tocbot after you load the script }}
<script>
    tocbot.init({
        // Where to render the table of contents.
        tocSelector: '.gh-toc',
        // Where to grab the headings to build the table of contents.
        contentSelector: '.gh-content',
        // Which headings to grab inside of the contentSelector element.
        headingSelector: 'h2, h3, h4',
        // Ensure correct positioning
        hasInnerContainers: true,

        orderedList: false,
    });
</script>
Disable Ordered List

orderedList: false is added to remove the order a, b, c, d in the TOC, as you can order the headers yourself if necessary.

3 Conclusion

With above simple tweak, the issues of the primitive TOC have been fixed perfectly, hope it helps you to prettify your Ghost website with a functional TOC.

💡
Above tweaks might not work for all themes, but please follow the ideas to tweak per your need.

Appendix

In-depth Ghost Tutorials

Tutorials
A library of resources to help you to customize, build, and create beautiful Ghost sites
Ghost Official Tutorials