# Create a custom page TOC ("mini TOC") with Javascript

**URL:** <https://discourse.gohugo.io/t/create-a-custom-page-toc-mini-toc-with-javascript/16665>\
**Category:** tips & tricks\
**Created:** [January 26, 2019, 11:08pm UTC](https://discourse.gohugo.io/t/create-a-custom-page-toc-mini-toc-with-javascript/16665 "2019-01-26T23:08:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sharonl](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/sharonl/32/3236_2.png) [@sharonl](https://discourse.gohugo.io/u/sharonl)\
**Post date:** [January 26, 2019, 11:08pm UTC](https://discourse.gohugo.io/t/create-a-custom-page-toc-mini-toc-with-javascript/16665/1 "2019-01-26T23:08:26Z")

</div>

On our site, we use custom JS code to create a page TOC (“mini TOC”) from `h2` headings on the page, instead of Hugo’s `TableofContents` partial (unless the custom `toc` page param is set to `hugo`). To my recollection, the main incentive for the custom implementation was to also include in the mini TOC headings created with shortcodes. I originally shared our implementation in response to a question in [Shortcode processing order](https://discourse.gohugo.io/t/shortcode-processing-order/16554/), as this implementation also works to include in the TOC headings from a file that is included using a shortcode.

### list.html & single.html Theme Default Partials

The theme **\_default** partials include this code:

```auto
{{ partial "mini-toc" . }}

```

### mini-toc.html Theme Partial

```auto
{{ $headers := findRE "<h[2].*?>(.|\n])+?</h[2]>" .Content }}

{{ if and (ge (len $headers) 1) (ne $.Params.toc "none") }}
  <div class="toc">
    <div class="mini-toc">
      <div class="mini-toc-header">
        <i class="fa fa-caret-right laptop" aria-hidden="true"></i>
        <span>On This Page</span>
        <i class="fa fa-caret-right desktop" aria-hidden="true"></i>
      </div>
    {{ if eq $.Params.toc "hugo" }}
      {{ .TableOfContents }}
    {{ else }}
      <nav role="navigation" id="TableOfContents">
        <ul class="toc-js"></ul>
      </nav>
  {{ end }}
    </div>
  </div>
{{ end }}

```

### mini-toc.js

```auto
// Create a custom page TOC ("mini TOC")
function buildMiniToc() {
  var ToC;
  $('.content h2').each(function (i, el) {
    // Replace &lt;` and `&gt;` in the HTML headings with `<` and `>` to
    // support using these character entities in the source heading text and
    // avoid interpreting them as HTML tags. The current drawback is that
    // escaped `\&lt;` or `\&gt;` uses in the source heading text will appear
    // in them mini-TOC as `<` and `>` instead of `&lt;` and `&gt;`.
    var title = $(el).text().replace(/</g, '&lt;').replace(/>/g, '&gt');
    var link = '#' + $(el).attr('id');
    ToC = '<li><a href="' + link + '">' + title + '</a></li>';

    // Display the mini TOC only if page has TOC-level headings (currently, h2)
    $('ul.toc-js').append(ToC);
  });

  $(".mini-toc-header").click(function() {
    $("#TableOfContents").slideToggle(200);
    $(".mini-toc i").toggleClass("fa-caret-right");
    $(".mini-toc i").toggleClass("fa-caret-down");
  });

  $(window).scroll(function() {
    var windScroll = $(this).scrollTop();
    windScroll > 200 ? $('#scroll-top').show() : $('#scroll-top').hide();
    if (windScroll) {
      $(".doc-content > h2, h3, h4").each(function() {
        if ($(this).position().top <= windScroll + 56) {
          var activeHeader = $("#TableOfContents").find('[href="#' + $(this).attr('id') + '"]');

          if (activeHeader.length) {
            $("#TableOfContents").find("a").removeClass("active");
            activeHeader.addClass("active");
          }
        }
      })
    }
  }).scroll();

  $(window).resize(function() {
   if ( $(window).width() > 1143 ){
       $('.mini-toc-header i').removeClass('fa-caret-right').addClass('fa-caret-down');
       $('#TableOfContents').show();
   } else {
       $('.mini-toc-header i').removeClass('fa-caret-down').addClass('fa-caret-right');
       $('#TableOfContents').hide();
   }
  }).resize();
}

```

---

<div class="post-metadata">

**Author:** ![maiki](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/maiki/32/16384_2.png) [@maiki](https://discourse.gohugo.io/u/maiki)\
**Post date:** [January 27, 2019, 1:15am UTC](https://discourse.gohugo.io/t/create-a-custom-page-toc-mini-toc-with-javascript/16665/2 "2019-01-27T01:15:29Z")

</div>

@sharonl thanks for the comprehensive write up! I moved it to a #tips-tricks topic. I was wondering, could you share the site where it is deployed? So we can point folks to a live demo. 🙂

---

<div class="post-metadata">

**Author:** ![sharonl](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/sharonl/32/3236_2.png) [@sharonl](https://discourse.gohugo.io/u/sharonl)\
**Post date:** [January 27, 2019, 8:46pm UTC](https://discourse.gohugo.io/t/create-a-custom-page-toc-mini-toc-with-javascript/16665/3 "2019-01-27T20:46:06Z")

</div>

This is our doc site: [https://www.iguazio.com/docs/](https://www.iguazio.com/docs/). It’s not an open-source site, though.  
You can see an example of the mini TOC on most pages — for example, [https://www.iguazio.com/docs/tutorials/latest-release/getting-started/containers/](https://www.iguazio.com/docs/tutorials/latest-release/getting-started/containers/).  
The TOC is very similar to the Hugo mini TOC.
