A tiny (~3 KB), dependency-free floating table of contents you can drop into any site via CDN — no build step, no theme editing. Built for the GreedyLabs Ghost blog, but works on any HTML page.
Live demo & visual configurator:https://ghost-toc-plugin.greedylabs.kr
- Auto-generates a TOC from the headings in your article
- Floats beside your content and follows as you scroll
- Highlights the section you're currently reading
- Hides automatically on narrow screens (configurable)
- Korean/Unicode heading slugs, dark-mode aware
- Configure everything with
data-*attributes - Fully namespaced under
greedylabs-ghost-toc(classes + CSS vars) so it never clashes with your theme's styles
Add this once. For Ghost: Settings → Code injection → Site Footer.
<linkrel="stylesheet" href="https://cdn.jsdelivr.net/gh/GreedyLabs/ghost-toc-plugin@1/toc.css"><scriptsrc="https://cdn.jsdelivr.net/gh/GreedyLabs/ghost-toc-plugin@1/toc.min.js"
data-content=".gh-content"
data-headings="h2,h3"
data-position="right"
data-title="목차"></script>
@1resolves to the latestv1.x.xrelease and jsDelivr auto-minifies it (the.minsuffix). Pin an exact version like@v1.0.5for a fully reproducible build. If jsDelivr is ever down, Statically mirrors the same paths atcdn.statically.io/gh/GreedyLabs/ghost-toc-plugin@main.
Not Ghost-specific. Anywhere you can inject a <script> (including Notion-based
hosts that allow custom code, such as oopy or super.so) point data-content at
the article container. For Notion that is .notion-page-content, and its
headings nest deeper, so include h4:
<scriptsrc="https://cdn.jsdelivr.net/gh/GreedyLabs/ghost-toc-plugin@1/toc.min.js"
data-content=".notion-page-content"
data-headings="h2,h3,h4"></script>All set as data-* attributes on the <script> tag.
| Attribute | Default | Description |
|---|---|---|
data-content | .gh-content, article, main, .post-content, .entry-content | CSS selector for the article body |
data-headings | h2,h3 | Which headings to list (e.g. h2,h3,h4) |
data-position | right | right or left |
data-title | 목차 | Title above the list (empty string hides it) |
data-accent | auto | Active-item color. Defaults to your Ghost theme accent (--ghost-accent-color), then #1a73e8. Set only to override. |
data-min-width | 1200 | Hide the TOC below this viewport width (px) |
data-min-headings | 2 | Don't render if fewer headings than this |
data-top | 100 | Distance from top of viewport (px) |
data-width | 240 | Panel width (px) |
data-gap | 28 | Gap between content and panel (px) |
Override the CSS variables on .greedylabs-ghost-toc (or globally) — no need to fork
the CSS:
.greedylabs-ghost-toc {
--greedylabs-ghost-toc-accent:#e8590c; /* active link */--greedylabs-ghost-toc-muted:rgba(0,0,0,.5); /* inactive text */--greedylabs-ghost-toc-border:rgba(0,0,0,.1); /* the rail */
}Theme accent is automatic. On a Ghost site the active color already follows your
publication's accent color (--ghost-accent-color) with no setup. Only set
data-accent (or --greedylabs-ghost-toc-accent) if you want a different color.
<asideclass="greedylabs-ghost-toc greedylabs-ghost-toc--right"><navclass="greedylabs-ghost-toc__inner"><pclass="greedylabs-ghost-toc__title">목차</p><ulclass="greedylabs-ghost-toc__list"><liclass="greedylabs-ghost-toc__item greedylabs-ghost-toc__item--h2"><aclass="greedylabs-ghost-toc__link" href="#...">…</a></li>
…
</ul></nav></aside>The active link gets greedylabs-ghost-toc__link--active.
- Place the
<script>withoutdefer/async(the footer is fine) so it can read its owndata-*options. - On screens narrower than
data-min-width, or when there isn't room beside the content, the panel hides itself.
MIT © GreedyLabs