Make Internal Links Scroll Smoothly with JavaScript
Pages: 1, 2, 3, 4, 5, 6
How to Scroll
Of course, we have to have a smoothScroll() function, too. This is the complicated aspect, because it's all about finding an object's position on the page, and different browsers achieve this in various ways. The marvelous Andrew Clover has written a summary of the process that's used to find this position across browsers; we'll use this solution extensively here.
First, our smoothScroll() function is an event handler, so when it's called (that is, when a user clicks one of our internal links), we need to retrieve the link that was clicked. Netscape-class browsers pass an event object to each handler; Internet Explorer stores these details in the global window.event object.
if (window.event) {
target = window.event.srcElement;
} else if (e) {
target = e.target;
} else return;
This code sets the clicked link as the target in a cross-browser fashion. Well, nearly. Mozilla will sometimes pass you the text node within a link as the clicked item. We need to check whether or not the target is a text node (that is, whether its nodeType is 3), and take its parent if it is.
if (target.nodeType == 3) { target = target.parentNode; }
Just to be paranoid, we also check that what we've got is an a tag, in case we've missed something:
if (target.nodeName.toLowerCase() != 'a') return;
Now we need to find the destination: the <a name> tag that corresponds to the part after the hash in our clicked link. Links have a hash attribute that contains the # and the section that appears after it in the URL, so let's now walk through all of the links in the document and check whether their name attributes are equal to the hash part of the clicked link:
// First strip off the hash (first character)
anchor = target.hash.substr(1);
// Now loop all A tags until we find one with that name
var allLinks = document.getElementsByTagName('a');
var destinationLink = null;
for (var i=0;i<allLinks.length;i++) {
var lnk = allLinks[i];
if (lnk.name && (lnk.name == anchor)) {
destinationLink = lnk;
break;
}
}
// If we didn't find a destination, give up and let the browser do
// its thing
if (!destinationLink) return true;



