Streaming live at 10am (PST)

How to create CMS dynamic table of contents (Step by step tutorial)

#1

Base on this plugin (There are many more similar libraries):
http://projects.jga.me/toc/

Example of blog posts (CMS)

1/5:

The normal process (Bind the rich text area) for post collection page


2/5 - toc div

Add empty div with class of toc


3 - add custom code

Before body copy-paste the custom code below (The code is very small - less than 1KB (774 bytes). No cdn for this library)

<script>
 /*!
 * toc - jQuery Table of Contents Plugin
 * v0.3.2
 * http://projects.jga.me/toc/
 * copyright Greg Allen 2014
 * MIT License
*/
!function(a){a.fn.smoothScroller=function(b){b=a.extend({},a.fn.smoothScroller.defaults,b);var c=a(this);return a(b.scrollEl).animate({scrollTop:c.offset().top-a(b.scrollEl).offset().top-b.offset},b.speed,b.ease,function(){var a=c.attr("id");a.length&&(history.pushState?history.pushState(null,null,"#"+a):document.location.hash=a),c.trigger("smoothScrollerComplete")}),this},a.fn.smoothScroller.defaults={speed:400,ease:"swing",scrollEl:"body,html",offset:0},a("body").on("click","[data-smoothscroller]",function(b){b.preventDefault();var c=a(this).attr("href");0===c.indexOf("#")&&a(c).smoothScroller()})}(jQuery),function(a){var b={};a.fn.toc=function(b){var c,d=this,e=a.extend({},jQuery.fn.toc.defaults,b),f=a(e.container),g=a(e.selectors,f),h=[],i=e.activeClass,j=function(b,c){if(e.smoothScrolling&&"function"==typeof e.smoothScrolling){b.preventDefault();var f=a(b.target).attr("href");e.smoothScrolling(f,e,c)}a("li",d).removeClass(i),a(b.target).parent().addClass(i)},k=function(){c&&clearTimeout(c),c=setTimeout(function(){for(var b,c=a(window).scrollTop(),f=Number.MAX_VALUE,g=0,j=0,k=h.length;k>j;j++){var l=Math.abs(h[j]-c);f>l&&(g=j,f=l)}a("li",d).removeClass(i),b=a("li:eq("+g+")",d).addClass(i),e.onHighlight(b)},50)};return e.highlightOnScroll&&(a(window).bind("scroll",k),k()),this.each(function(){var b=a(this),c=a(e.listType);g.each(function(d,f){var g=a(f);h.push(g.offset().top-e.highlightOffset);var i=e.anchorName(d,f,e.prefix);if(f.id!==i){a("<span/>").attr("id",i).insertBefore(g)}var l=a("<a/>").text(e.headerText(d,f,g)).attr("href","#"+i).bind("click",function(c){a(window).unbind("scroll",k),j(c,function(){a(window).bind("scroll",k)}),b.trigger("selected",a(this).attr("href"))}),m=a("<li/>").addClass(e.itemClass(d,f,g,e.prefix)).append(l);c.append(m)}),b.html(c)})},jQuery.fn.toc.defaults={container:"body",listType:"<ul/>",selectors:"h1,h2,h3",smoothScrolling:function(b,c,d){a(b).smoothScroller({offset:c.scrollToOffset}).on("smoothScrollerComplete",function(){d()})},scrollToOffset:0,prefix:"toc",activeClass:"toc-active",onHighlight:function(){},highlightOnScroll:!0,highlightOffset:100,anchorName:function(c,d,e){if(d.id.length)return d.id;var f=a(d).text().replace(/[^a-z0-9]/gi," ").replace(/\s+/g,"-").toLowerCase();if(b[f]){for(var g=2;b[f+g];)g++;f=f+"-"+g}return b[f]=!0,e+"-"+f},headerText:function(a,b,c){return c.text()},itemClass:function(a,b,c,d){return d+"-"+c[0].tagName.toLowerCase()}}}(jQuery);
</script>

4/5 - Initialize

Initialize the plugin.
Jquery class selctor (".toc") - read her about jquery selectors:

Again keep in mind the selectors must match (In my example .toc class and .rich-text-block class)
**paste this code after the code from step 3

<script>
/* initialize toc plugin */
$('.toc').toc({
    'selectors': 'h1,h2,h3', //elements to use as headings
    'container': '.rich-text-block', //element to find all selectors in
    'prefix': 'toc', //prefix for anchor tags and class names
    'highlightOnScroll': true, //add class to heading that is currently in focus
    'highlightOffset': 100, //offset to trigger the next headline
 });
 </script>

5/5 - publish

Publish the site

Click

http://new-landing-page-94e5db.webflow.io/post/20-myths-about-web-design

Styles:

If you want to create “multi-level” effect (This is not really nested UL) -

Add extra margin for h3 list elements (Better UI):

<style>
.toc-h3{
  margin-left: 20px; 
}
</style>

scrollspy effect

Use .toc-active to style the current menu active (For sidebars menu with active state change on scroll)


scroll:

Related JS option: 'highlightOffset': 100, //offset to trigger the next headline

#webflow blog posts table of contents

Weaknesses: Other TOC libraries know to create nested lists (And number lists) for complex data. Advantages: Tiny code, fast, simple.

3 Likes
Adding contents structure(TOC) to CMS
Set up table of contents on Blog CMS
How to link to a section within a CMS item (blog posts)
ToC on a blog post?
#2

Thanks for this! I manage to set it up :wink:

Anyone can explain to me how/where to apply CSS for the ToC?

Thanks!
Ohyoon

#3

This is the classes the JS added to the LI (list element).
'prefix': 'toc', //prefix for anchor tags and class names
Than the plugin “generate” this class:
toc-h2
and
toc-h3
and
toc-h4
image

So you 100% knows the class name. How to create styles. By webflow create UL list and use this class name for the li

Now webflow generate in the CSS this class

.toc-h2 {
    background-color: rgb(125, 245, 191);
    color: rgb(250, 17, 17);
    font-size: 33px;
    line-height: 40px;
    font-style: italic;
    text-decoration: line-through;
}

So when you publish the site the design change:

style active state

create combo-class for “toc-active” (For sticky sidebars).

Publish the site - and the first toc (Active) style change:

style the link inside

One small problem. No way to style this
.li a (The link inside the list item). You should manually add custom code (before head or as embed html)

<style>
.toc-h2 a, .toc-h3 a, .toc-h4 a{
   color: orange;
   font-weight: 800;
   /*more styles her */
}
/* specific class for h2 level toc */
.toc-h2 a, .toc-h3 a, .toc-h4 a{
   text-align: right;
}

</style>

Read her about descendant-selector: