[Blogger] A plug-in that automatically generates a table of contents from headings



t f B! P L

[Blogger] A plug-in that automatically generates a table of contents from headings

enter image description here

This article is an article that mechanically translates This URL into English.

In this article, I will introduce how to automatically generate a table of contents in Blogger.

Blogger is a very good blog service, such as “no ad display”, “custom domain available”, and “Can be monetized with Adsence” even though it is free.

However, like WordPress, you can not install the plug-in, so the functionality of the standard widget provided by Blogger may be lacking.

In particular, Blogger does not have the ability to automatically generate a table of contents.

This time, I created a plug-in that automatically generates a table of contents in Blogger.
By introducing this plug-in, you can easily generate a table of contents automatically, like WordPress “TOC +” plug-in.

In fact, the table of contents shown below in this article is automatically generated by the plug-in introduced this time.


  1. Automatically detect heading tags (h2, h3, h4 …) and automatically generate a table of contents
  2. jQuery not used (plain JavaScirpt)
  3. With link button of show / hide of table of contents
  4. Indexing is possible even if header tags (h2, h3, h4) are formed hierarchically
  5. Lightweight, compressed CSS, JavaScript
  6. Optional control of table of contents display
  7. Automatically assign paragraph numbers

Introduction of plug-in

Back up the theme

Just in case, let’s backup the current theme.
The backup method is as follows.

  1. From the Blogger administration screen, click [Theme]-> [Backup / Restore].
  2. Click Download theme to download the current theme


  1. On the theme screen, click [Edit HTML] to display the HTML
  2. Add the following code just before </ head>
<!-- [START] Start TOC plug-in-->
<b:if cond='data:blog.pageType == "item"'>
    //Change the following options to your liking
    var toc_options = {
      target: ["h2", "h3", "h4"],
      autoNumber:  true,
      condTargetCount: 2,
      insertPosition: "firstHeadBefore",
      showToc: true,
      width: "auto",
      marginTop: "20px",
      marginBottom: "20px",
      indent: "20px",
      postBodySelector: ".widget.Blog"

    //Please do not change this compressed Javascript
    (function(i){var j=0;document.addEventListener(&quot;DOMContentLoaded&quot;,function(){var p=document.querySelector(toc_options.postBodySelector);if(p==null||typeof p===&quot;undefined&quot;){reutrn}if(toc_options.target.length==0){return}rootContent=h(toc_options,p);if(rootContent.children.length&gt;=toc_options.condTargetCount){var q=c(rootContent);o(q)}});function h(q,p){var u=q.target.length;var t=function(E,D,w){var z=q.target[E];var x=E&lt;u-1?q.target[E+1]:&quot;&quot;;var y=&quot;toc_headline_&quot;+(++j);var F=g(z,m(D),E+1,y);w.children.push(F);D.id=y;var A=f(D);if(x==&quot;&quot;){return}while(true){if(A==null||typeof A===&quot;undefined&quot;){break}if(b(A)==z){break}if(b(A)==x){t(E+1,A,F)}else{var B=A.getElementsByTagName(x);for(var C=0;C&lt;B.length;C++){t(E+1,B[C],F)}}var A=f(A)}};var r=g(&quot;ROOT&quot;,&quot;&quot;,0);var v=p.getElementsByTagName(q.target[0]);for(var s=0;s&lt;v.length;s++){t(0,v[s],r,&quot;&quot;)}return r}function c(s){var r=document.createElement(&quot;div&quot;);r.classList.add(&quot;b-toc-container&quot;);r.style.marginTop=toc_options.marginTop;r.style.marginBottom=toc_options.marginTop;if(toc_options.width==&quot;100%&quot;){r.style.display=&quot;block&quot;}else{r.style.width=toc_options.width}var q=document.createElement(&quot;p&quot;);var w=document.createElement(&quot;span&quot;);var v=document.createElement(&quot;span&quot;);var u=document.createElement(&quot;span&quot;);v.classList.add(&quot;b-toc-show-wrap&quot;);u.classList.add(&quot;b-toc-show-wrap&quot;);var y=document.createElement(&quot;a&quot;);w.innerText=&quot;table of contents&quot;;v.innerText=&quot;[&quot;;u.innerText=&quot;]&quot;;y.href=&quot;javascript:void(0);&quot;;q.appendChild(w);q.appendChild(v);q.appendChild(y);q.appendChild(u);var t=function(z){var p=typeof z===&quot;boolean&quot;?z:e(r,&quot;hide&quot;);if(p){y.innerText=&quot;hide&quot;;r.classList.remove(&quot;hide&quot;)}else{y.innerText=&quot;show&quot;;r.classList.add(&quot;hide&quot;)}};y.addEventListener(&quot;click&quot;,t);t(toc_options.showToc);var x=document.createElement(&quot;ul&quot;);s.children.forEach(function(z,p){n(x,z,(p+1)+&quot;&quot;)});r.appendChild(q);r.appendChild(x);return r}function n(s,u,w){var p=document.createElement(&quot;li&quot;);var q=document.createElement(&quot;a&quot;);p.style.paddingLeft=toc_options.indent;q.href=&quot;#&quot;+u.id;if(toc_options.autoNumber){var t=document.createElement(&quot;span&quot;);t.classList.add(&quot;toc-number&quot;);t.innerText=w}var v=document.createElement(&quot;span&quot;);v.classList.add(&quot;toc-text&quot;);v.innerText=u.text;if(toc_options.autoNumber){q.appendChild(t)}q.appendChild(v);p.appendChild(q);s.appendChild(p);if(u.children.length&gt;0){var r=document.createElement(&quot;ul&quot;);p.appendChild(r);u.children.forEach(function(y,x){n(r,y,w+&quot;.&quot;+(x+1))})}}function o(q){var r=null;var p=document.querySelector(toc_options.postBodySelector);if(toc_options.insertPosition==&quot;firstHeadBefore&quot;||toc_options.insertPosition==&quot;firstHeadAfter&quot;){r=p.querySelector(toc_options.target[0])}else{if(toc_options.insertPosition==&quot;top&quot;){r=p}}if(r==null){return}if(toc_options.insertPosition==&quot;firstHeadBefore&quot;){k(r,q)}else{if(toc_options.insertPosition==&quot;firstHeadAfter&quot;){a(r,q)}else{if(toc_options.insertPosition==&quot;top&quot;){k(r,q)}}}}function g(q,r,p,s){return{tagName:q,text:r,children:[],nestLevel:p,id:s}}function m(p){return p.innerText}function f(p){return p.nextElementSibling}function d(p){return p.previousElementSibling}function b(p){return p.tagName.toLowerCase()}function e(p,q){return p.classList.contains(q)}function l(p){return p.parentNode}function a(q,s){var r=l(q);var p=f(q);if(r!=null&amp;&amp;p!=null){r.insertBefore(s,p)}}function k(p,r){var q=l(p);if(q!=null){q.insertBefore(r,p)}}})(window);
  <style type="text/css">
    .b-toc-container{background:#f9f9f9;border:1px solid #aaa;padding:10px;margin-bottom:1em;width:auto;display:table;font-size:95%}.b-toc-container p{text-align:center;margin:0;padding:0}.b-toc-container ul{list-style-type:none;list-style:none;margin:0;padding:0}.b-toc-container>ul{margin:15px 0 0}.b-toc-container.hide>ul{display:none}.b-toc-container ul li{margin:0;padding:0 0 0 20px;list-style:none}.b-toc-container ul li:after,.b-toc-container ul li:before{background:0;border-radius:0;content:""}.b-toc-container ul li a{text-decoration:none;color:#008db7!important;font-weight:400}.b-toc-container ul li .toc-number{margin:0 .5em 0 0}.b-toc-container ul li .toc-text:hover{text-decoration:underline}
<!-- [END] END TOC plug-in-->
  1. After pasting the code, click Save Theme on the screen to save the content.

This completes the plug-in settings.
After saving, please look at your blog. Surely, I think that the table of contents is displayed on your blog.


You can specify options for the TOC auto-generation plug-in introduced this time. You can change the displayed contents of the table of contents by changing the options.

Introduce how to set options.

How to set options

The copied code has a part where toc_options = {...} is written.
Edit this JSON directly to change the TOC display options.

For the setting contents of options, please refer to “Description of each option” described later.

   var toc_options = {
     target: ["h2", "h3", "h4"],
     autoNumber: true,
     condTargetCount: 2,
     insertPosition: "firstHeadBefore",
     showToc: true,
     width: "auto",
     marginTop: "20px",
     marginBottom: "20px",
     indent:  "20px",
     postBodySelector: ".widget.Blog"

Description of each option

  • target

Specify a heading tag in the range of h1 to h6 to create a table of contents.

  • autoNumber

Specifies whether the table of contents is automatically numbered.

When ** true ** is specified, hierarchical serial numbers are automatically assigned in the order of 1 → 1.1 → 1.1.1.
** false ** Do not display the serial number.

  • condTargetCount

Specify the number of headings to display the table of contents.
For example, if you specify 2, the table of contents is displayed when there are two or more top-level headings specified with thetarget option.


Specify the display position of the table of contents from the following three.

Value Display position of table of contents
firstHeadBefore Before the first heading
firstHeadAfter After the first heading
top top of article


Specifies the initial TOC display state.

When ** true ** is specified, the table of contents is displayed in the initial state.
If you specify ** false **, the table of contents will be closed.


Specifies the width of the table of contents.

** auto ** Automatically adjust the width to the number of characters in the table of contents
** ○○% ** Width specified as a percentage (100% full width display TOC)
** ○○ px ** Specify the width in pixels


Specifies the margin at the top of the table of contents.


Specifies the bottom margin of the table of contents.


Specifies the indent width for the table of contents.

  • postBodySelector

※ This option is recommended to change only those who are familiar with CSS selectors and JavaScript.

Specify the tag of the article body, which is the creation range of the table of contents, with the CSS selector.
If heading tags (h2 to h4) are used in addition to the article text, setting this option will allow you to create a table of contents with only the heading tags in the article text.


There are many people who use WordPress even around you, but I’m glad if the number of people who use Blogger can be increased by one with this convenient plug-in.




Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。