Cette solution n'est plus recommandée en raison des changements de comportement du navigateur. Voir d'autres réponses.
Fondamentalement, si une ancre est utilisée, nous nous lions à l'événement de défilement de Windows. L'idée étant que le premier événement de défilement doit appartenir au repositionnement automatique effectué par le navigateur. Lorsque cela se produit, nous effectuons notre propre repositionnement, puis supprimons l'événement lié. Cela empêche les défilements de page suivants de perturber le système.
$(document).ready(function() {
if (window.location.hash) {
//bind to scroll function
$(document).scroll( function() {
var hash = window.location.hash
var hashName = hash.substring(1, hash.length);
var element;
//if element has this id then scroll to it
if ($(hash).length != 0) {
element = $(hash);
}
//catch cases of links that use anchor name
else if ($('a[name="' + hashName + '"]').length != 0)
{
//just use the first one in case there are multiples
element = $('a[name="' + hashName + '"]:first');
}
//if we have a target then go to it
if (element != undefined) {
window.scrollTo(0, element.position().top);
}
//unbind the scroll event
$(document).unbind("scroll");
});
}
});