Skip to main content

How do I use the table of contents on my announcements?

Give readers a quick way to jump to the section they care about, and customize the look with your own CSS.

Summary

Long announcements can be hard to skim. The table of contents adds a sidebar next to your announcement that lists its headings, so readers can jump straight to the section they're looking for instead of scrolling through the whole post.


How it works

  • Once turned on, the table of contents is built automatically from the headings in your announcement — Heading 1 through Heading 4.

  • Indentation follows your heading levels, so subheadings nest under the section they belong to.

  • If your announcement skips a level — say it only uses Heading 2 and Heading 3 — the table of contents shifts everything in so the top level still reads flush left.

  • As readers scroll, the table of contents highlights whichever section is currently in view.

Turn on the table of contents

  1. Go to Settings > Customize page > General settings.

  2. Scroll towards the bottom of the page and turn on Show announcement table of contents.

  3. Structure your announcement content using Heading 1, Heading 2, Heading 3, and/or Heading 4 from the formatting toolbar — these are what populate the table of contents.

  4. Publish or preview the announcement to see it appear.

NOTE: This is a workspace-wide setting. Once it's turned on, every announcement with headings will show a table of contents. There is no separate switch per announcement.


Customize the look with custom CSS

Want the table of contents to better match your brand? You can restyle the rail color, active-state indicator, indent spacing, and text size with custom CSS.

Default vs. custom styling

Both columns below use the same table of contents but only the CSS values change. If you'd like to update the styling to the example of the right then copy the code below.

Custom CSS to copy/paste:

Add this under Settings > Customize Page > Custom HTML & CSS, in the Custom CSS box. It's safe to add alongside any code already there.

/* ============================================================
TABLE OF CONTENTS
============================================================ */

.toc {
--toc-rail: #E5E7EB; /* resting rail */
--toc-rail-active: #0070F2; /* active section's rail segment */
--toc-text: #1A2733; /* resting link */
--toc-text-active: #0070F2; /* active + hover link */
--toc-step: 16px; /* indent added per level */
list-style: none !important;
margin: 0 !important;
padding: 0 !important;
}

.toc ul { list-style: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; }
.toc li { margin: 0 !important; padding: 0 !important; border: 0 !important; }

.toc a {
display: block !important;
color: var(--toc-text) !important;
text-decoration: none;
font-size: 14px !important;
line-height: 1.5 !important;
padding: 6px 0 6px 16px !important;
border-left: 2px solid var(--toc-rail) !important;
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
}
.toc a:hover { color: var(--toc-text-active) !important; }

.toc li li a { padding-left: calc(16px + var(--toc-step)) !important; }
.toc li li li a { padding-left: calc(16px + var(--toc-step) * 2) !important; }
.toc li li li li a { padding-left: calc(16px + var(--toc-step) * 3) !important; }

.toc a.is-active,
.toc a.active,
.toc a[aria-current] {
color: var(--toc-text-active) !important;
border-left-color: var(--toc-rail-active) !important;
}

Custom head CSS to copy/paste:

The CSS above styles an .is-active class, but something needs to add that class as the reader scrolls past each section. Paste this into the Custom head box (same Settings > Customize Page > Custom HTML & CSS screen) to wire it up:

<script>
(function () {
var OFFSET = 130; // px from top of viewport where a section counts as "current"

function onScroll() {
var links = [].slice.call(document.querySelectorAll('.toc a[href^="#"]'));
if (!links.length) return;
var ids = [];
links.forEach(function (a) {
var id = decodeURIComponent(a.getAttribute('href').slice(1));
if (ids.indexOf(id) === -1) ids.push(id);
});
var activeId = ids[0];
for (var i = 0; i < ids.length; i++) {
var el = document.getElementById(ids[i]);
if (el && el.getBoundingClientRect().top <= OFFSET) activeId = ids[i];
}
links.forEach(function (a) {
var id = decodeURIComponent(a.getAttribute('href').slice(1));
a.classList.toggle('is-active', id === activeId);
});
}

window.addEventListener('scroll', onScroll, { passive: true });

var tries = 0;
var timer = setInterval(function () {
onScroll();
if (++tries > 25) clearInterval(timer);
}, 200);
onScroll();
})();
</script>

Four variables in the CSS you will want to edit:

  • --toc-rail-active — the blue rail marking the active section

  • --toc-text-active — the color of the active section's text

  • --toc-text — the muted gray used for inactive links

  • --toc-step — how far each nested level indents

Change those four values (plus the font size and spacing further down) to match your brand.


Troubleshooting

  • If the table of contents isn't showing up, first confirm Show announcement table of contents is turned on under Settings > Customize page, then check that your announcement uses actual Heading 1–4 styles (not just bold or larger text) and has more than one heading.

  • If your custom CSS isn't applying, double-check it pasted into the Custom CSS box without errors — invalid CSS won't save.

  • If the active section isn't highlighting as readers scroll, confirm the scroll-tracking script is in the Custom head box, not the Custom CSS box.

Did this answer your question?