There are many hyperlinks like < a href=«#idName» > … < /a > on different web pages that do not take you to another page, but rather to a place (target) on the same page. This is common practice for large articles with an index in which every item is a link to the corresponding heading. In the case of a footnote – the superscript is linked to the bottom of the article and the footer itself has a link back to the text. There is a great number of articles written in this fashion in different network encyclopedias and in journals.
Unfortunately most of todays browsers simply jump to the place where the hyperlink points. This is very different from scrolling that happens slowly and takes some notable time in a way that it can give the reader a sense of how much information is being skipped.
Rather unfortunate, isn’t it?
Fortunately there’s a jQuery plugin that let’s one create the effect of text scrolling upon clicking the target link. This scroll simulation looks just like scrolling by hand but happens automatically and much faster – within a second by default. In this way the user gets the sense of the amount of information going by but doesn’t have the time to get bored.
The plugin is called jQuery.Local.Scroll, it requires jQuery and another plugin – jQueryScrollTo which it encapsulates. Once jQuery and both aforementioned plugins are installed a function call that will activate automatic scrolling for all internal hyperlinks this simple:
$($.localScroll());
Everything would be nice if not for the fact that by default such scrolling is just that – srolling: the document is scrolled in the browser until the end. That’s all.
In order to fully simulate scrolling to the in-page hyperlink the above requires «#idName» added to the address (in the browser address page). The browser’s Back button would do no good in this case: even though the user wants to return back to the index (or back to text from the footnote) – the browser suddenly returns to the previous page.
Ariel Flesler (author of jQuery.LocalScroll plugin) recommends including the «hash» parameter in order to make the simulation perfect by adding «#idName» to the page address:
$($.localScroll({
hash: true
}));
If this is done – the # part of the address changes and the Back button starts to work as expected.
But is this scrolling really simulated perfectly? Not really. Issues begin to arise if a «:target» selector (it appeared in CSS3) is being used. For example, a style rule *:target { background-color: red } should highlight the part of the document where the hyperlink has just taken the browser. In the new browsers it really does (according to MDC this selector is suported in Firefox 1.0, Opera 9.4, Safari 1.3 and newer). However, if the ($.localScroll()) or $($.localScroll({hash: true})) call is being used, Firefox scrolls smoothly, but the CSS highlighting is switched off. Completely.
What to do?
I would’ve never guessed the reason for such behavior, but found the answer in the current (1.2.7) source code of LocalScroll.
It turns out Ariel Flesler decided to make his life simpler and instead of waiting for the scroll to end (and adding some event to it that would apply the # part of the address after the scrolling is over) the plugin assigns the # part of the address the desired value of
location = link.hash;
Simple, isn’t it? But this assignment automatically (and immediately) scrolls the document to the #target and the idea of smooth scrolling is dropped, you say.
That’s right!
And since Ariel Flesler has already decided to make his life simple, he’s following his intention to the end: first he takes away the «id=”idName”» attribute (or «name=”idName”») at the target’s location and then assigns the # part of the address the desired value (scrolling doesn’t happen). Then he kills this freshly created empty element and returns the revoked attribute to the destination – it’s only then that he starts the smooth scroll.
Of course Firefox applies the «:target» selector to it’s new empty element (which is later destroyed). It then brutally ignores the destruction of the element and the further appearance of the same attribute on another. I haven’t decided whether to consider this a Firefox bug. Neither have I checked what the behavior of Opera, Safari or Chrome would be in this situation. I know enough now to fix this.
The solution is to invoke $.localScroll() with a decent interpreter and works exactly after the scrolling is done:
$.localScroll({
onAfter: function(target){
location = ‘#’ + ( target.id || target.name );
}
});
That’s it! Now wasn’t that simple!