Evitar el desplazamiento automático del navegador al actualizar

95

Si va a una página a y se desplaza, actualice la página se actualizará en el lugar donde la dejó. Esto es genial, sin embargo, esto también ocurre en páginas donde hay una ubicación de anclaje en la URL. Un ejemplo sería si hiciera clic en un enlace http://example.com/post/244#comment5y actualizara la página después de mirar a su alrededor, no estaría en el ancla y la página salta. ¿Hay alguna forma de evitar esto con javascript? Para que no importa lo que sea, siempre navegará hasta el ancla.

ThomasReggi
fuente
¿Está bien una solución de jQuery o desea js simples?
mrtsherman

Respuestas:

16

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");
        });
    }

});
mrtsherman
fuente
Un caso de uso que estoy pensando que debería tenerse en cuenta es si el usuario se desplaza por la página antes de que se produzca el desplazamiento automático. Según recuerdo, el desplazamiento automático solo ocurre después de que la página se haya cargado por completo. Si el usuario se desplaza antes, se cancela el desplazamiento automático. Por lo tanto, necesitaría alguna forma de distinguir entre el desplazamiento iniciado por el usuario y el iniciado por el navegador. No sé cómo hacer esto, pero según recuerdo, es posible.
mrtsherman
1
¡Booyah! Este fue un divertido problema nocturno. Sin embargo, le digo a mi jefe que es culpa tuya cuando me quedo dormido en mi escritorio. Acabo de hacer un cambio rápido para eliminar la declaración de devolución. Esto interfirió con la desvinculación que agregué para el evento de desplazamiento.
mrtsherman
Inicialmente hice que esto funcionara dentro de un pequeño archivo de ejemplo básico para verificarlo. Una vez que confirmé que funcionaba, me desconcertó ver cómo no estaba funcionando dentro de mi proyecto. A través del proceso de eliminación, logré encontrar una declaración de estilo única en mi archivo css que estaba causando fallas. Fue la aplicación de una fuente externa. Envolví su código en una función y ahora lo estoy pasando a un controlador $ (window) .load () dentro del controlador doc.ready. Parece que funciona ahora (con un ligero parpadeo de página inicial). ¡Gracias por el código! Avíseme si esta es una solución sólida o no.
ThomasReggi
1
No funcionará si tiene contenido que se carga después de que se carga la página; Ej: tener 2 div que se llenarán desde ajax con banners.
Decebal
@FlashThunder: ¿puedes definir "no funciona"? ¿Publicar un mensaje de consola?
mrtsherman
152

En Chrome, incluso si fuerza scrollTop a 0, saltará después del primer evento de desplazamiento.

Debes vincular el pergamino a esto:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

Por tanto, se engaña al navegador para que crea que estaba al principio antes de la actualización.

josetapadas
fuente
5
Mucho más útil que la respuesta aceptada si no quiere perder el tiempo con el desplazamiento.
Dan Abramov
2
Esto no funciona en Chrome 33. Quiero decir, se desplaza hacia la parte superior antes de cargar la nueva página. Sin embargo, el navegador aún recuerda la posición de desplazamiento anterior de alguna manera y realiza el mismo desplazamiento automático a esa posición.
Haralan Dobrev
1
Probado en Chrome 36, Firefox 30 e IE 11. ¡Funciona muy bien!
Fizzix
24
Para implementación que no sea jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa
5
¿Por qué eligió el evento 'beforeunload' en lugar de 'unload'? Mis pruebas muestran que el último permite evitar saltar a la parte superior antes de que el navegador descargue la página.
Aleksandr Zonov
76

Para deshabilitar la restauración automática de desplazamiento, simplemente agregue esta etiqueta a la sección del encabezado.

<script>history.scrollRestoration = "manual"</script>

No es compatible con IE. Compatibilidad del navegador.

imos
fuente
3
Esta sería la mejor respuesta si estuviera disponible en IE / Edge. Sin embargo, puede votar para que se implemente aquí: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy
4
Esta debería ser una respuesta realmente correcta en 2019. Ninguno de los otros métodos funciona al 100%.
Limbo
2
Puedo confirmar que esta es la mejor solución. Otras soluciones aquí no funcionan en Mobile Safari y pueden ser ridículas. Esto funciona perfectamente.
user3330820
20

Después de varios fallos finalmente logré hacer el truco. anzo es correcto aquí, ya que usar beforeunloadhará que la página salte a la parte superior cuando un usuario vuelva a cargar la página o haga clic en un enlace. Así unloades claramente la forma de hacer esto.

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

Forma de Javascript (Gracias ProfNandaa ):

window.onunload = function(){ window.scrollTo(0,0); }

EDITAR: 16/07/2015

El problema del salto sigue ahí con Firefox incluso con unloadevent.

Janaka Dombawela
fuente
3
Esta solución es mucho mejor que la beforeunloadsolución porque evita saltar a la parte superior de la página en recargas y clics de anclaje.
BradGreens
@BradGreens Con Chrome moderno, el evento onunload también se activa cuando el usuario cambia a otras pestañas, lo cual es inesperado. onbeforeunload sigue siendo una solución alternativa válida.
Telvin Nguyen
@TelvinNguyen ¿Puede dar algún recurso sobre esto? Probé esto en Google Chrome 72 y todavía funciona bien para mí.
Janaka Dombawela
@JanakaDombawela Lo que dije: Cambiar la nueva pestaña que causaría problemas es incorrecto. Sin embargo, puede ver que el evento onunload en este ejemplo no se activa correctamente, incluso con jQuery 1.9.1 vs jQuery 1.8.3. onunload no es confiable. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen
3

Aquí hay un enfoque más general. En lugar de intentar evitar que el navegador se desplace (o salte a la parte superior como se vería), simplemente restauro la posición anterior en la página. Es decir, estoy grabando el desplazamiento y actual de la página en localStorage y me desplazo a esta posición una vez que la página se ha cargado.

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}
Oliver Schafeld
fuente
2

Puede poner un # al final para que la página se cargue en la parte superior.

Funciona en todos los navegadores, móviles y de escritorio, porque es muy simple.

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

// Esto carga la página con un # al final.

Daut
fuente
Si pruebo esto en mi servidor directamente, funciona como magia. Pero, mi cms me está dando un error de marcado. No puedo entender qué es eso.
Alice
1
si está utilizando wordpress, cambie $ por jQuery
Herzling
1

Esto funciona para mi.

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });
Alex divirtiéndose
fuente
-2

Deberias ser capaz de.

Onload, compruebe si window.location.hashtiene un valor. Si es así, tome el elemento con una identificación que coincida con el valor hash. Encuentre la posición del elemento (llamadas recursivas a offsetTop / offsetLeft) y luego pase esos valores al window.scrollTo(x, y)método.

Esto debería desplazar la página hasta el elemento deseado.

nikmd23
fuente
3
Esto no impide que los navegadores realicen un desplazamiento automático. De eso se trata esta pregunta.
Haralan Dobrev