Here is a way to do Table of Contents (ToC)

The ID is generated by Ghost core, so you have to contact them or do a pull request on github yourself

Awesome thanks! Also if you use VSCode grab Markdown All in One then you can generate the ToC VS Code (ctrl + shift + p and type toc and Insert it.

This is great. Thanks for sharing this

1 Like

This works great in general, however when I use the code inject for the footer it puts a TOC on the home page as well as the posts except for adding the card at the bottom of the page. I tried you second code that should eliminate the bottom card but it actually did nothing in my theme. No TOC at all. I haven’t figure out a way to get it to ignore the main landing page yet. If anyone does please let us know or if I can get it figured out I’ll post it.

I don’t want to edit the html of each post page as that can get out of hand quickly on a large site.

Sorry, I got confused on who’s code I was using. I actually used

And I finally did get it to work correctly once I read it right and placed the code at the bottom of the post in a HTML card.

Hey all :wave:, we’ve recently put together a new tutorial to show you how to add a Table Of Contents to your Ghost site. Take a look, hope this helps:

PS. If you have any feedback let us know!


Very good tutorial indeed! Thanks for the insight.

1 Like

This is very cool. Thank you for working on this.

I noticed that the sticky table of contents shifts the text to the left and widens the text box, so there are more words per line. Is there a way to keep the text centered and the text box the same width? I think keeping the text in the center and having fewer words per line makes the content easier to read.

My testing with sticky TOC (compare with the Lyra Demo without TOC):

For non-sticky TOC, the h3 headers add an extra line in the TOC and only appear under the first h2:

How does one retain the current form of content being centered and occupying let’s say about 40% width, while still having the sticky TOC on the side?

Yes, I’m wondering the same thing: Here is a way to do Table of Contents (ToC)

@theodorechu @kairos This is all possible by adjusting the values in the CSS. The example provided in the tutorial is designed to get you started. Changing the values for the .post-full-content CSS from the ones in the tutorial ( is a good place to start :slight_smile:

OK, thanks @DavidDarnes. I looked at the advanced styling, and I noticed a problem. Here’s some feedback:

On Casper/Lyra, the max-width of .inner is 1040px, and .post-full-content is inside .inner, so the max-width of .post-full-content is also 1040px.

Suppose we want to preserve the width of .post-content at the default 700px.

The min-width of the sticky TOC according to the advanced styling tutorial is 260px. We probably don’t want to make this any smaller.

The sticky TOC is on the right side of .post-content, so we can center the .post-content column by adding another column on the left side of .post-content. We can also assign a min-width of 260px.

The width of the three columns together is 260px + 700px + 260px = 1220px. This is greater than the width allowed by .inner, so the columns are off-center.

The result is the following:

Do you have any suggestions on how to fix this?

Do you have any suggestions on how to fix the problem of the h3 headers not showing in the TOC?

@theodorechu are you using CSS float: right for the div containing the TOC?

I don’t think so. I didn’t specify any float, and the div containers are in a grid, so the float is irrelevant, right?

My CSS for the div containing the TOC is the same as shown in the tutorial. I think the TOC appears to the right because the total width of the columns (1220px) is greater than the width of .inner, so the columns overflow to the right.

I was thinking you could try floating the TOC div, so your layout does not need a third column. It would also leave the original layout intact, requiring fewer additional modifications.

If you want to either post or pm me the URL for your test site I can test and show you my thinking.

1 Like

Alternatively, I can spin up a test site in just a few minutes, upload your current work-in-progress and we can work it out together.

I followed the tutorial linked above by @DavidDarnes and added the TOC to the Casper theme, and added this CSS to make it fixed at the top right and exclude/hide it on smaller screens:


.toc {
    position: fixed;
    top: 100px;
    right: 0;
    width: 250px;
    font-size: .8em;

ol.toc-list {
    margin: 0;
    padding-right: 20px;

@media (max-width: 1170px) {
    .toc {


The result is shown on this page:

Also, in Casper and Lyra, the Featured Image can be made more narrow (matching the width of the rest of the post content), if you want to keep it out of the way of the fixed TOC styled as above, by also adding this to the CSS:

.post-full-image {
    background: transparent;
    padding: 0 170px;

The styles provided in the tutorial are just a starting point, you can use CSS however you like to make something custom just for you :slight_smile:

I made the choice to move the post content area to the left so the table of contents nav had space on the right hand side. You’ll notice that if you reduce the browser width in the layout you have made the table of contents will get cut off by the browser window, or wrap under the content.

As for the h3 headings, they get revealed when the h2 immediately above them has been clicked. You can see this happening in this gif when “Working with images in posts” is clicked:

Either that or you don’t have enough content under the heading. The collapsing feature can be turned off in Tocbot by adding collapseDepth: 2 to the configuration. More into on the Tocbot docs:

I’ve got a problem with headings that come directly after images in the post content.

When I click on a heading in the side-panel Table of Contents the content successfully scrolls to the proper place (the heading ends up at the top of the screen). However, when I click on a heading in the side-panel whose heading in the content is directly after an image the screen scrolls and ends up with the image being at the top of the screen, the heading then below the image.

I can somewhat fix this with a workaround by inserting an HTML card with <p>&nbsp;</p> between the image and the heading (simply <p></p> doesn’t work), but then that ends up creating a gap (which I suppose I could remedy with CSS).

Anybody know of some way that this could be fixed without having to resort to that workaround?

EDIT: Solution below.

That seems like a strange bug, especially since it’s not happening in the gif (one of the headings clicked is directly after an image). I’m guessing this is a CSS layout issue