Fork me on GitHub

Table of Contents plugin for Bootstrap

Build Status

This Bootstrap plugin allows you to generate a table of contents for any page, based on the heading elements (<h1>, <h2>, etc.). It is meant to emulate the sidebar you see on the Bootstrap documentation site.

This page is an example of the plugin in action – the table of contents you see on the left (or top, on mobile) was automatically generated, without having to manually keep all of the navigation items in sync with the headings.


On top of the normal Bootstrap setup (see their Getting Started guide), you will need to include the Bootstrap Table of Contents stylesheet and JavaScript file.

<!-- add after bootstrap.min.css -->
<link rel="stylesheet" href="">
<!-- add after bootstrap.min.js -->
<script src=""></script>

Unminified versions are also available.

Next, pick one of the two options below.

Via data attributes


Create a <nav> element with a data-toggle="toc" attribute.

<nav id="toc" data-toggle="toc"></nav>

You can put this wherever on the page you like. Since this plugin leverages Bootstrap’s Scrollspy plugin, you will also need to add a couple attributes to the <body>:

<body data-spy="scroll" data-target="#toc">

Via JavaScript

If you need customization.

If you prefer to create your navigation element another way (e.g. within single-page apps), you can pass a jQuery object into Toc.init().

<nav id="toc"></nav>
$(function() {
  var navSelector = '#toc';
  var $myNav = $(navSelector);
    target: navSelector

See the Scrollspy documentation for more information about initializing that plugin.


When calling Toc.init(), you can either pass in the jQuery object for the <nav> element (as seen above), or an options object:

  $nav: $('#myNav'),
  // ...

All options are optional, unless otherwise indicated.

option type notes
$nav jQuery Object (required) The element that the navigation will be created in.
$scope jQuery Object The element where the search for headings will be limited to, or the list of headings that will be used in the navigation. Defaults to $(document.body).


The following options can be specified at the heading level via data-toc-* attributes.

Displayed text

By default, Bootstrap TOC will use the text from the heading element in the table of contents. If you want to customize what is displayed, add a data-toc-text attribute with the desired text. For example:

<h2 data-toc-text="Short text">Longer text</h2>

displays “Longer text” as the heading, but “Short text” in the sidebar.


To prevent a particular heading from being added to the table of contents, add a data-toc-skip boolean attribute.

<h2 data-toc-skip>Some heading you don't want in the nav</h2>


This plugin isn’t opinionated about where it should be placed on the page, but a common use case is to have the table of contents created as a “sticky” sidebar. We will leverage the Affix plugin for this, and wrap the <nav> element in a <div> with a Bootstrap column class (see information about the Grid). As an example putting it all together (similar to this page):

<body data-spy="scroll" data-target="#toc">
  <div class="container">
    <div class="row">
      <!-- sidebar, which will move to the top on a small screen -->
      <div class="col-sm-3">
        <nav id="toc" data-spy="affix" data-toggle="toc"></nav>
      <!-- main content area -->
      <div class="col-sm-9">

You may also want to include this in your stylesheet:

nav[data-toggle='toc'] {
  margin-top: 30px;

/* small screens */
@media (max-width: 768px) {
  /* override the Affix plugin so that the navigation isn't sticky */
  nav.affix[data-toggle='toc'] {
    position: static;

  /* PICK ONE */
  /* don't expand nested items, which pushes down the rest of the page when navigating */
  nav[data-toggle='toc'] .nav .active .nav {
    display: none;
  /* alternatively, if you *do* want the second-level navigation to be shown (as seen on this page on mobile), use this */
  nav[data-toggle='toc'] .nav .nav {
    display: block;


See also

This plugin was heavily inspired by: