In-page links (or, links that jump to specific areas of the current page) are definitely useful for lengthy or text-heavy sites, and often essential when these pages are consumed by screenreaders or "legacy" mobile devices. But they can also be disorienting for many reasons — did I just move up the page? Down it? With the instantaneous transition the browser provides by default, a user is left to guess.
I wouldn't be the first to suggest overriding this behavior with a scrolling effect that illuminates which direction you've traveled, and also how far. A global, automatic solution would be ideal. For animated effects, a robust JavaScript library can save a lot of time, and I'll use the popular jQuery library for this example. Out of the box, jQuery does not have this functionality, and although there is an appropriate plugin, I was determined to cobble together my own solution so as to avoid loading an additional plugin only to use it in this one instance.
A quick seach brought me to Learning jQuery, where there is a great solution I've shamelessly copied (with very minor modification). I will walk through this solution below, although I recommend reading the original breakdown at Learning jQuery.
$(document).ready(function() { $('a[href*=#]').click(function() { var target = $('a[name=' + this.hash.split('#')[1] + ']'); if (target.length) { var targetOffset = target.offset().top - 2; $('html,body').animate({scrollTop: targetOffset}, 'fast'); return false; } }); });
-
Attach a click event to every anchor element with an
hrefattribute beginning with a '#' (e.g. any in-page link).$('a[href*=#]').click(function() { ... });
-
Get the link's destination on the page using its
hashproperty.hashrefers to the portion of any URL that begins with '#'. Use this in another selector to get the anchor element on this page with the correspondingnameattribute. Save this as thetargetvariable.var target = $('a[name=' + this.hash.split('#')[1] + ']');
-
If this element exists on the page (
targetcollection length greater than zero), get the distance from the top of the page to this element and save it astargetOffset(note that I subtract 2 to give a little bit of breathing room visually; this way the element doesn't touch the top of the browser frame).if (target.length) { var targetOffset = target.offset().top - 2; //... }
-
Now use jQuery's built-in
animate()method to scroll the page itself (grabbing thehtmlorbodyelement in case the browser is in quirksmode).$('html,body').animate({scrollTop: targetOffset}, 'fast');
-
Return
falsebecause now you don't actually follow this link.return false;
You can see this in action in many areas of this site as long as you have javascript enabled. For example, try clicking the "top ↑" link in the right-hand column.
It's of note that the
animate() method takes a
variety of arguments. I've only supplied the target for scrollTop and
the speed ("fast"), but it's a very powerful function. A third argument,
easing, is available via a plugin, and can make the animation look
much more natural. In my case, however, I opted for less code overhead
and omitted this. The final argument, callback, provides for some
interesting possibilities, but I also found it to be unnecessary for
this case.