Impedisci lo scorrimento automatico del browser all'aggiornamento


95

Se vai a una pagina a e scorri, aggiorna la pagina si aggiornerà nel punto in cui l'hai lasciata. Questo è ottimo, tuttavia ciò si verifica anche nelle pagine in cui è presente una posizione di ancoraggio nell'URL. Un esempio potrebbe essere se si fa clic su un collegamento http://example.com/post/244#comment5e si aggiorna la pagina dopo essersi guardati intorno, non si sarebbe all'ancora e la pagina salta. C'è un modo per impedirlo con javascript? In modo che non importa cosa navigherai sempre verso l'ancora.


Va bene una soluzione jQuery o vuoi semplicemente js?
mrtsherman

Risposte:


16

Questa soluzione non è più consigliata a causa dei cambiamenti nel comportamento del browser. Vedi altre risposte.

Fondamentalmente, se viene utilizzato un ancoraggio, ci colleghiamo all'evento di scorrimento di Windows. L'idea è che il primo evento di scorrimento deve appartenere al riposizionamento automatico effettuato dal browser. Quando ciò si verifica, effettuiamo il nostro riposizionamento e quindi rimuoviamo l'evento associato. In questo modo si evita che i successivi scorrimenti di pagina disturbino il 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");
        });
    }

});

Un caso d'uso a cui penso che dovrebbe essere preso in considerazione è se l'utente scorre la pagina prima che si verifichi lo scorrimento automatico. Come ricordo, lo scorrimento automatico avviene solo dopo che la pagina è stata caricata completamente. Se l'utente scorre prima, lo scorrimento automatico viene annullato. Quindi sarebbe necessario un modo per distinguere tra scorrimento avviato dall'utente e avviato dal browser. Non so come farlo, ma se ricordo bene è possibile.
mrtsherman

1
Booyah! Questo è stato un divertente problema a tarda notte. Sto dicendo al mio capo che è colpa tua quando mi addormento alla mia scrivania però. Ho appena apportato una rapida modifica per rimuovere la dichiarazione di reso. Ciò ha interferito con la separazione che ho aggiunto per l'evento di scorrimento.
mrtsherman

Inizialmente ho ottenuto questo lavoro all'interno di un piccolo file di esempio di base per verificarlo. Una volta confermato che funzionava, ero sconcertato di come non funzionasse all'interno del mio progetto. Attraverso il processo di eliminazione sono riuscito a trovare una singola dichiarazione di stile nel mio file css che ne causava l'errore. Era l'applicazione di un font esterno. Ho inserito il tuo codice in una funzione e ora lo sto passando a un gestore $ (window) .load () all'interno del gestore doc.ready. Ora sembra funzionare (con un leggero sfarfallio della pagina iniziale). Grazie per il codice! Fammi sapere se questa è una soluzione solida o meno.
ThomasReggi

1
Non funzionerà se hai contenuti che vengono caricati dopo il caricamento della pagina; Es: avere 2 div che verranno riempiti da ajax con banner.
Decebal

@FlashThunder - puoi definire "non funziona"? Pubblicare un messaggio sulla console?
mrtsherman

151

Su Chrome, anche se imposti scrollTop su 0, salterà in seguito dopo il primo evento di scorrimento.

Dovresti associare la pergamena a questo:

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

Quindi il browser è indotto a credere che fosse all'inizio prima dell'aggiornamento.


5
Molto più utile della risposta accettata se non vuoi scherzare con lo scorrimento.
Dan Abramov

2
Questo non sta facendo il lavoro in Chrome 33. Voglio dire che scorre verso l'alto prima di caricare la nuova pagina. Tuttavia, il browser ricorda ancora in qualche modo la posizione di scorrimento precedente ed esegue lo stesso scorrimento automatico in quella posizione.
Haralan Dobrev

1
Testato su Chrome 36, Firefox 30 e IE 11. Funziona molto bene!
Fizzix

24
Per l'implementazione non jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa

5
Perché hai scelto l'evento "beforeunload" invece di "unload". I miei test mostrano che l'ultimo consente di evitare di saltare all'inizio prima che la pagina venga effettivamente scaricata dal browser.
Aleksandr Zonov

74

Per disabilitare il ripristino dello scorrimento automatico, aggiungi questo tag alla sezione principale.

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

Non è supportato da IE. Compatibilità del browser.


3
Questa sarebbe la risposta migliore se fosse disponibile in IE / Edge. Puoi votare per l'implementazione qui: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy

4
Questa dovrebbe essere davvero una risposta corretta nel 2019. Nessuno degli altri metodi funziona al 100%.
Limbo

2
Posso confermare che questa è la soluzione migliore. Altre soluzioni qui non funzionano su Mobile Safari e possono essere janky. Funziona perfettamente.
user3330820

20

Dopo numerosi fallimenti finalmente sono riuscito a fare il trucco. anzo è corretto qui in quanto l'utilizzo beforeunloadfarà saltare la pagina all'inizio quando un utente ricarica la pagina o fa clic su un collegamento. Quindi unloadè il modo chiaro per farlo.

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

Modo Javascript (Grazie ProfNandaa ):

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

EDIT: 16/07/2015

Il problema del salto è ancora presente con Firefox anche con l' unloadevento.


3
Questa soluzione è molto migliore della beforeunloadsoluzione perché impedisce di saltare all'inizio della pagina durante i ricaricamenti e i clic di ancoraggio.
BradGreens

@BradGreens Con Chrome moderno, l'evento onunload viene attivato anche quando l'utente passa ad altre schede, il che è inaspettato. onbeforeunload è ancora una soluzione alternativa valida.
Telvin Nguyen,

@TelvinNguyen Puoi dare qualche risorsa su questo? L'ho provato su Google Chrome 72 e funziona ancora bene per me.
Janaka Dombawela

@JanakaDombawela Quello che ho detto: Spostare una nuova scheda che causerebbe problemi non è corretto. Tuttavia, puoi vedere l'evento onunload in questo esempio non attivato correttamente, anche con jQuery 1.9.1 rispetto a jQuery 1.8.3. onunload non è affidabile. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen

3

Ecco un approccio più generale. Invece di cercare di impedire al browser di scorrere (o saltare all'inizio come apparirebbe), ripristino semplicemente la posizione precedente sulla pagina. Cioè sto registrando l'offset y corrente della pagina in localStorage e scorro fino a questa posizione una volta che la pagina è stata caricata.

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
}

2

Puoi semplicemente mettere un # alla fine in modo che la pagina venga caricata in alto.

Funziona su tutti i browser, mobile e desktop, perché è così semplice.

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

});

// Questo carica la pagina con un # alla fine.


Se provo questo direttamente sul mio server, funziona come per magia. Ma il mio CMS mi sta dando un errore di mark-up. Non riesco a capire cosa sia.
alice

1
se stai usando wordpress cambia $ per jQuery
Herzling

1

Questo funziona per me.

    //Reset scroll top

    history.scrollRestoration = "manual"

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

-2

Dovresti essere capace di.

Onload, controlla se window.location.hashha un valore. In tal caso, prendi l'elemento con un ID che corrisponde al valore hash. Trova la posizione dell'elemento (chiamate ricorsive a offsetTop / offsetLeft) e poi passa quei valori nelwindow.scrollTo(x, y) metodo.

Questo dovrebbe far scorrere la pagina fino all'elemento desiderato.


3
Ciò non impedisce ai browser di eseguire uno scorrimento automatico. Ecco di cosa parla questa domanda.
Haralan Dobrev
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.