Anchor link menu

This javascript creates an internal page navigation menu, with anchor links pointing to each H2 element on the current page.

The advantage of using javascript instead of static HTML is that the menu is generated automatically every time the page is loaded, so you don't need to edit the menu when you make changes to the page's H2 elements.

Browser support

Should work from IE9 and in any other browser in use today.

Demo

The script is used on all my web design demo pages, including this one (just below the top heading, floated right).

How it works

  1. The script first checks if two or more H2 elements exist on the page, since a menu with just one link would be unnecessary.
  2. Next, the script gives each H2 element an ID value of the form "section1", "section2", etc. If an ID is already used in the static HTML, the number after "section" is incremented until an unused value is found.
  3. After this, a UL list of links pointing to the H2 element IDs is created, and then inserted in a NAV element. The plain text content in each H2 element is used as link text.
  4. Finally, the NAV element is inserted right after the page's first H1 element (note: the script does not check if an H1 element actually exists on the page).

The menu script

The full script is shown below. It can be added to a SCRIPT element anywhere in the BODY or HEAD sections of the web page. The menu's container NAV element can be styled with the CSS selector nav#page_anchors.

function page_anchors()
{
	var h1=document.getElementsByTagName('h1');
	var h2=document.getElementsByTagName('h2');

	// a menu is only created if more than one
	// H2 element exists in the static HTML
	if(h2.length>1)
	{
		var ul=document.createElement('ul');
		for(var i=0; i<h2.length; i++)
		{
			// let the ID values start with 1 instead of 0
			var j=1*i+1;

			// check that an ID doesn't already exist
			while(document.getElementById('section'+j))
			{
				j++;
			}

			h2[i].id='section'+j;
			var li=document.createElement('li');
			li.innerHTML='<a href="#section'+j+'">'+h2[i].textContent+'</a>';
			ul.appendChild(li);
		}
		var nav=document.createElement('nav');
		nav.id='page_anchors';
		nav.innerHTML='<p>On this page:</p>';
		nav.appendChild(ul);
		h1[0].parentNode.insertBefore(nav, h1[0].nextSibling);
	}
}
if(window.addEventListener)
{
	window.addEventListener('load', page_anchors, false);
}

published: Jan 16, 2016
last modified: Jan 26, 2017