Automatically generate a Wikipedia-style Table of Contents with JavaScript

The heading title is self-explanatory. An illustrative example of this done manually:

    .toc {
      border: thin solid lightgray;
      background-color: whitesmoke;


  <h1>Article title</h1>
  <hr />
  <p>Some introductory text.</p>

  <span id="toc">
    <table class="toc">
              <li><a target="_blank" rel="nofollow" href="#1">Heading</a></li>
                <li><a target="_blank" rel="nofollow" href="#1.1">Sub-heading</a></li>
                  <li><a target="_blank" rel="nofollow" href="#1.1.1">Sub-sub-heading</a></li>
              <li><a target="_blank" rel="nofollow" href="#2">Second heading</a></li>
                <li><a target="_blank" rel="nofollow" href="#2.1">Second sub-heading</a></li>
                  <li><a target="_blank" rel="nofollow" href="#2.1.1">Second sub-sub-heading</a></li>
              <li><a target="_blank" rel="nofollow" href="#3">See also</a></li>
              <li><a target="_blank" rel="nofollow" href="#4">Notes &amp; References</a></li>
              <li><a target="_blank" rel="nofollow" href="#5">Further reading</a></li>
              <li><a target="_blank" rel="nofollow" href="#6">External links</a></li>

  <div id="Contents">
    <h1 id="1">Heading</h1>
    <hr />
    <h2 id="1.1">Sub-heading</h2>
    <h3 id="1.1.1">Sub-sub-heading</h3>
    <h1 id="2">Second heading</h1>
    <hr />
    <h2 id="2.1">Second sub-heading</h2>
    <h3 id="2.1.1">Second sub-sub-heading</h3>
    <h1 id="3">See also</h1>
    <hr />
    <h1 id="4">Notes &amp; References</h1>
    <hr />
    <h1 id="5">Further reading</h1>
    <hr />
    <h1 id="6">External links</h1>
    <hr />



  1. Notice the nested lists re-start their count from 1 instead of progressing from the parent enumeration (e.g. “1, 1.1, 1.1.1”).
  2. Doing this manually is time consuming.
  3. All promptly available “Table of Contents” libraries do not function or style by default like the one in Wikipedia articles. Most of these libraries are not exactly “lightweight” and this is also an incovenience.

You can use CSS counters adjusted to render expected result