An Extensive Dynamic Table of Contents Generator for Webflow CMS
Table of Contents (ToC) Generator for Webflow CMS
Updated 2023 Version
I have done versions of this script in the past. This one is the most extensive with 4 different functionalities:
- Dynamic Table of Contents:
The script automatically generates a table of contents based on the headers within your content. This helps users understand the structure of your content at a glance and navigate directly to the section they're interested in. - Stylable Based on Heading Level:
Each table of contents item is automatically given a CSS class that corresponds to its heading level (e.g.,toc_h2
,toc_h3
), allowing for customization of style for each heading level. - Active Section Highlighting:
As the user scrolls through the page, the script identifies the current section being viewed and highlights it in the table of contents. This provides a visual cue to help users keep track of their position in the document. - Interoperability with CMS:
This script is designed to work with a content management system (CMS), allowing you to specify which heading levels to include in the table of contents.
The value provided by this script lies in function 4 because it improves the usability for long-form content:
- In the past all h tags were considered by the script to generate the ToC.
- Now, You can choose to what depth you want your ToC to be generated from right in your Webflow CMS (or any other headless CMS).
In general, a ToC improves usability for any content designed for reading:
- Enhanced Reader Experience: By offering a table of contents and active section highlighting, readers can quickly navigate to the sections that interest them and maintain their location in long articles or posts. This can significantly improve the reader's experience, especially on long and complex pages.
- SEO Benefits: By structuring your content with headings and providing anchor links to specific sections, you can potentially improve your content's search engine optimization (SEO). Search engines like Google use headings to understand the content's structure and topics, and anchor links make your page more navigable for users coming from search results.
- Accessibility: This approach is also beneficial from an accessibility perspective. It assists screen readers and other assistive technologies in understanding the organization of the page content, thus improving the accessibility of your webpage.
This script now provides a relatively simple and effective way to enhance the navigability of your webpage, improve reader experience, and potentially boost SEO, all of which are critical for a great blog or any other content-rich website.
Documentation for the Table of Contents (ToC) Generator
This script automatically generates a dynamic and stylable table of contents (ToC) from selected heading levels in a webpage. It creates unique anchor links for each heading and monitors the user's scroll position to highlight the active section in the ToC. The generator can be easily customized by specifying which heading levels (e.g., h2, h3, etc.) should be included in the ToC.
How It Works
The script follows these steps:
- It retrieves the ToC container and the heading selectors from the webpage.
- It assigns a unique ID to each heading based on its content, and creates a corresponding anchor link in the ToC.
- It uses the Intersection Observer API to monitor which heading is currently in the viewport as the user scrolls through the page.
- When a heading enters the viewport, the script highlights its corresponding link in the ToC by adding an 'active' class to it.
Usage
- Copy and paste the script into your webpage. The script should be placed within
<script>
tags, preferably just before the closing</body>
tag for better performance. - Ensure that your page has a container for the ToC with the ID
toc
and a content container with the IDcontent
. - By default, the script includes headings level h2 through h6 in the ToC. If you want to specify different heading levels, you can either
- hard code it: replace the string in the
headingsSelector
variable with the levels you want to include, separated by commas (e.g.,"h2,h3"
) and no spaces! - Or: Create a text field in your Webflow CMS where you can choose the levels you want to include, separated by commas (e.g.,
"h2,h3"
- and no spaces!) directly in your CMS when you write a blogpost. Then, you have to replace the string in theheadingsSelector
variable with a field in Webflow.
- Now, the script automatically assigns each heading in the ToC a class of
tocitem
andtoc_hX
, whereX
is the level of the heading (e.g.,h2
). You can use these classes to style the ToC items in your CSS. - The script also assigns an 'active' class to the ToC item corresponding to the heading that is currently in the viewport. You can use this class to highlight the active item in your CSS.
ToC Script
<!-- generate a TOC styleabel by headings level -->
<script>
let toc = document.querySelector("#toc");
let headingsSelector = "[wire up your Webflow dynamic field here]"; // Selector for Headings selected in CMS
// If no value provided, default to all headings-except h1
if (!headingsSelector || headingsSelector.trim() === "") {
headingsSelector = "h2,h3,h4,h5,h6";
}
let headings = Array.from(document.querySelector("#content").querySelectorAll(headingsSelector));
let tocItems = headings.map((heading, index) => {
let headingText = heading.textContent.trim().toLowerCase();
headingText = headingText.replace(/[^a-z0-9\s]+/gi, '').replace(/\s+/g, '-');
let id = ${headingText}-${index}
; // ensure uniqueness
heading.setAttribute("id", id);
heading.classList.add("anchor");
const item = document.createElement("a");
item.textContent = heading.textContent;
item.href = #${id}
;
item.classList.add("tocitem", toc_${heading.tagName.toLowerCase()}
);
toc.appendChild(item);
return item; // return the created tocItem
});
// Use Intersection Observer API to determine when a section becomes visible
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const id = entry.target.getAttribute("id");
if (entry.isIntersecting) {
document.querySelectorAll(".active").forEach((z) => {
z.classList.remove("active")
});
document.querySelector(a[href="#${id}"]
).classList.add("active");
}
});
}, { rootMargin: '0px 0px -75% 0px' });
// Observe each heading
headings.forEach(heading => {
observer.observe(heading);
});
</script>
Customization
You can easily customize this script according to your needs. For example:
- If you want to include all heading levels in the ToC, you can set
headingsSelector
to"h1,h2,h3,h4,h5,h6"
. - If you want to change the container of the ToC or the content, simply replace
"#toc"
or"#content"
in the script with the selector of your desired container. - You can modify the Intersection Observer's root margin in order to change when a heading is considered to be in the viewport.
Compatibility
This script uses modern JavaScript features and should work in all modern browsers. It does not rely on any libraries or frameworks, so it can be used in any JavaScript environment. Might not work in Internet Explorer, as the Intersection Observer API is not supported there.
Optimize Netlify Build Minutes and DecapCMS by Skipping Unnecessary Builds
Optimize Netlify Build Minutes and DecapCMS by Skipping Unnecessary Builds
Displaying Both the Publication and Update Dates on Webpages
Showing both the update and the publish date on your blog / web page seems to be difficult for Search Engines and therefore it seems like only displaying “last updated” is the safer way. If your blog shows more than one date, you are probably confusing Google.
Localization: The "hreflang" Tag Accross Different Domains
John Mueller on how to use the hreflang tags across domains for the localization schemas: It doesn't matter if it's all on one domain or across multiple domains. It should just be one clear place per country and language.
DecapCMS Markdown Guide: Handling URLs with Parentheses for Text Fragment Highlighting
Are broken links in your DecapCMS Markdown articles giving you a headache? never let parentheses break your links again: handle text fragment highlighting in Markdown. No more parentheses-induced troubles in your Github articles built with Netlify!
Leveraging a Small JavaScript for a Quick Multilingual Strategy in Webflow
A button that appears when there is an alternate language defined for your content, making your cotent more relevant to your users experiences. Implementing a Dynamic Language Switcher Button with JavaScript
Interactive URL Copy Feature in Webflow Using Clean JavaScript and Clipboard API
An interactive URL copy feature in Webflow. Using clean JavaScript and the powerful Clipboard API, making it easier for visitors to share your pages. Because who doesn’t appreciate a great user experience?
An Extensive Dynamic Table of Contents Generator for Webflow CMS
Boost your Webflow Blog's readability and SEO with a dynamic Table of Contents (ToC) generator. It automatically creates a stylable, navigable ToC from your headings, and enhances user experience by highlighting the active section during scrolling.
Styling Our Auto-Generated ToC in Webflow
Creating or Changing Slugs in DecapCMS (formerly Netlify CMS)
Changing the URL Slug of your post in DecapCMS in config.yaml using the slug key and name key
Smooth Scrolling to the Next Section with JavaScript and [foo](#next) markdown syntax
When I write [[`foo`](#next)`](#next)` markdown syntax in my content I want the reader to jump to the next section, the next anchor, on my webpage.
Vimeo vs YouTube Embed for your Website
Consider this when you decide between YouTube or Vimeo for Website embeds
Editorial Workflow in Decap CMs (formerly Netlify CMS)
README for ChatGPT and How to Write the Best Prompts
When answering prompts, does it help ChatGPT to be more specific and precise if you give it a set of definitions upfront?
Use Hash-symbol vs Triple-quotes Syntax for Commenting Python Code
Consider this when you choose the syntax for commenting code in Python
Dynamically Generated ToC with Webflow CMS
Generating ToC’s based on h2 and h3 headings of a rich text CMS element with active states in a sticky Table of Contents
Dynamic Social Media Share Buttons for Webflow CMS Blogposts
Add a Twitter button and a share on LinkedIn to your blogposts with sharing content generated from Webflow CMS
Calculate Read Time from Webflow CMS
Calculated a read time from Webflow CMS and add to your blog template.
Add Copy-able Code Blocks to Webflow CMS
Uses highlight.js and custom code to add code blocks where you can copy the code to rich text element of Webflow CMS