Esta solución ya no se recomienda debido a cambios en el comportamiento del navegador. Vea otras respuestas.
Básicamente, si se usa un ancla, nos vinculamos al evento de desplazamiento de Windows. La idea es que el primer evento de desplazamiento debe pertenecer al reposicionamiento automático realizado por el navegador. Cuando esto ocurre, hacemos nuestro propio reposicionamiento y luego eliminamos el evento vinculado. Esto evita que los siguientes desplazamientos de página estropeen el sistema.
$(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");
});
}
});