javascripthtmltableofcontents

Js Table of Content with anchor link does not scroll to desired tag


I have a small JS code that detects h1 to h6 tags and provides a table of content. The problem is that clicking on a title (example title 5) simply scrolls the page to the top, while I would like it to scroll to title 5. I'm new here to JS, so I'm not sure if I'm doing something wrong.

I appreciate any replies and suggestions, thanks.


Edit

Thanks to MrUpsidown's suggestion to add the ids to the h1 tags now the script works. I don't know if this is good practice, so I welcome suggestions that make the script better.

var headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
var toc = document.createElement('div');
toc.id = 'toc';
document.body.appendChild(toc);
for (var i = 0; i < headings.length; i++) {
  var heading = headings[i];
  var anchor = document.createElement('a');
  anchor.href = '#' + heading.id;
  anchor.innerHTML = heading.innerHTML;
  toc.appendChild(anchor);
}
#toc {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
}

#toc > a {
  padding: 10px;
}

#toc > a:hover {
  background: gray;
  color: #fff;
}
<h1 id="one">Title 1</h1>
<p>Sample Text 1</p>

<h1 id="two">Title 2</h1>
<p>Sample Text 2</p>

<h1 id="three">Title 3</h1>
<p>Sample Text 3</p>

<h1 id="four">Title 4</h1>
<p>Sample Text 4</p>

<h1 id="five">Title 5</h1>
<p>Sample Text 5</p>

<h1 id="six">Title 6</h1>
<p>Sample Text 6</p>


Solution

  • You certainly can do this with Javascript although I'd rather try to output HTML with unique and custom ids.

    In your loop, create a custom title

    let title = 'title'+ (i+1); // Create ids of title1, title2, etc.
    

    Then set the heading HTML id attribute with the computed title

    heading.id = title; // Set heading id with title
    

    Finally set the anchor href with the computed title

    anchor.href = '#' + title; // Set href with title
    

    var headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
    var toc = document.createElement('div');
    toc.id = 'toc';
    document.body.appendChild(toc);
    for (var i = 0; i < headings.length; i++) {
      var heading = headings[i];
      let title = 'title'+ (i+1); // Create ids of title1, title2, etc.
      heading.id = title; // Set heading id with title
      var anchor = document.createElement('a');
      anchor.href = '#' + title; // Set href with title
      anchor.innerHTML = heading.innerHTML;
      toc.appendChild(anchor);
    }
    #toc {
        display: flex;
        flex-direction: column;
        flex-wrap: nowrap;
    }
    
    #toc > a {
      padding: 10px;
    }
    
    #toc > a:hover {
      background: gray;
      color: #fff;
    }
    <h1>Title 1</h1>
    <p>Sample Text 1</p>
    
    <h1>Title 2</h1>
    <p>Sample Text 2</p>
    
    <h1>Title 3</h1>
    <p>Sample Text 3</p>