Verhindern Sie das automatische Scrollen des Browsers beim Aktualisieren

95

Wenn Sie zu einer Seite a gehen und herumblättern, wird die Seite an der Stelle aktualisiert, an der Sie sie verlassen haben. Dies ist großartig, tritt jedoch auch auf Seiten auf, auf denen sich in der URL eine Ankerposition befindet. Ein Beispiel wäre, wenn Sie auf einen Link http://example.com/post/244#comment5klicken und die Seite aktualisieren, nachdem Sie sich umgesehen haben, wären Sie nicht am Anker und die Seite springt herum. Gibt es eine Möglichkeit, dies mit Javascript zu verhindern? Damit egal was Sie immer zum Anker navigieren würden.

ThomasReggi
quelle
Ist eine jQuery-Lösung in Ordnung oder möchten Sie einfache js?
Mrtsherman

Antworten:

16

Diese Lösung wird aufgrund von Änderungen im Browserverhalten nicht mehr empfohlen. Siehe andere Antworten.

Wenn ein Anker verwendet wird, binden wir grundsätzlich an das Windows-Bildlaufereignis. Die Idee ist, dass das erste Bildlaufereignis zur automatischen Neupositionierung durch den Browser gehören muss. In diesem Fall positionieren wir uns neu und entfernen dann das gebundene Ereignis. Dies verhindert, dass nachfolgende Seitenrollen das System stören.

$(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
quelle
Ein Anwendungsfall, von dem ich denke, dass er berücksichtigt werden sollte, ist, wenn der Benutzer die Seite scrollt, bevor das automatische Scrollen erfolgt. Soweit ich mich erinnere, erfolgt das automatische Scrollen erst, nachdem die Seite vollständig geladen wurde. Wenn der Benutzer zuvor einen Bildlauf durchführt, wird der Autoscroll abgebrochen. Sie müssten also zwischen dem vom Benutzer initiierten Bildlauf und dem vom Browser initiierten unterscheiden. Ich weiß nicht, wie ich das machen soll, aber wenn ich mich recht erinnere, ist es möglich.
Mrtsherman
1
Booyah! Dies war ein lustiges Problem bis spät in die Nacht. Ich sage meinem Chef, dass es deine Schuld ist, wenn ich an meinem Schreibtisch einschlafe. Ich habe gerade eine schnelle Änderung vorgenommen, um die return-Anweisung zu entfernen. Dies störte die Entbindung, die ich für das Scroll-Ereignis hinzugefügt hatte.
Mrtsherman
Anfangs habe ich dies in einer kleinen grundlegenden Beispieldatei zum Auschecken gebracht. Als ich bestätigte, dass es funktioniert hat, war ich verblüfft darüber, dass es in meinem Projekt nicht funktioniert hat. Durch den Prozess der Eliminierung gelang es mir, eine einzelne Stildeklaration in meiner CSS-Datei zu finden, die einen Fehler verursachte. Es war die Anwendung einer externen Schriftart. Ich habe Ihren Code in eine Funktion eingeschlossen und übergebe ihn jetzt an einen $ (window) .load () -Handler im doc.ready-Handler. Es scheint jetzt zu funktionieren (mit einem leichten Flackern der ersten Seite). Danke für den Code! Lassen Sie mich wissen, ob dies eine solide Lösung ist oder nicht.
Thomas Reggi
1
Es funktioniert nicht, wenn Sie Inhalte haben, die nach dem Laden der Seite geladen werden. Bsp.: Mit 2 Div, die von Ajax mit Bannern gefüllt werden.
Decebal
@FlashThunder - kannst du definieren "funktioniert nicht"? Konsolennachricht posten?
Mrtsherman
151

Selbst wenn Sie in Chrome scrollTop auf 0 setzen, springt es nach dem ersten Scroll-Ereignis nachher.

Sie sollten die Schriftrolle daran binden:

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

Der Browser wird also ausgetrickst, um zu glauben, dass es am Anfang vor der Aktualisierung war.

Josetapadas
quelle
5
Viel nützlicher als die akzeptierte Antwort, wenn Sie nicht mit dem Scrollen herumspielen möchten.
Dan Abramov
2
Dies funktioniert in Chrome 33 nicht. Ich meine, es wird vor dem Laden der neuen Seite nach oben gescrollt. Der Browser merkt sich jedoch immer noch die vorherige Bildlaufposition und führt den gleichen automatischen Bildlauf zu dieser Position durch.
Haralan Dobrev
1
Getestet auf Chrome 36, Firefox 30 und IE 11. Funktioniert sehr gut!
Fizzix
24
Für Nicht-jQuery-Implementierung: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa
5
Warum haben Sie das Ereignis "beforeunload" anstelle von "entladen" gewählt? Meine Tests haben gezeigt, dass die letzte Möglichkeit, einen Sprung nach oben zu vermeiden, bevor die Seite wirklich vom Browser entladen wird.
Aleksandr Zonov
73

Um die automatische Bildlaufwiederherstellung zu deaktivieren, fügen Sie dieses Tag einfach zum Kopfbereich hinzu.

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

Es wird vom IE nicht unterstützt. Browser-Kompatibilität.

imos
quelle
3
Dies wäre die beste Antwort, wenn es in IE / Edge verfügbar wäre. Sie können jedoch dafür stimmen, dass es hier implementiert wird: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy
4
Dies sollte 2019 wirklich eine richtige Antwort sein. Keine der anderen Methoden funktioniert zu 100%.
Limbo
2
Kann bestätigen, dass dies die beste Lösung ist. Andere Lösungen funktionieren hier nicht auf Mobile Safari und können ruckelig sein. Das funktioniert perfekt.
user3330820
20

Nach einer Reihe von Fehlern habe ich es endlich geschafft, den Trick zu machen. anzo ist hier korrekt, da bei Verwendung beforeunloaddie Seite nach oben springt, wenn ein Benutzer die Seite neu lädt oder auf einen Link klickt. So unloadist der klare Weg, dies zu tun.

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

Javascript Weg (Danke ProfNandaa ):

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

EDIT: 16/07/2015

Das Sprungproblem ist bei Firefox auch bei unloadEreignissen noch vorhanden.

Janaka Dombawela
quelle
3
Diese Lösung ist viel besser als die beforeunloadLösung, da sie verhindert, dass beim erneuten Laden und Ankerklicken an den Anfang der Seite gesprungen wird.
BradGreens
@BradGreens Bei modernem Chrome wird das Ereignis onunload auch ausgelöst, wenn Benutzer zu anderen Registerkarten wechseln, was unerwartet ist. onbeforeunload ist immer noch eine gültige Problemumgehung.
Telvin Nguyen
@TelvinNguyen Können Sie eine Ressource dazu geben? Ich habe dies auf Google Chrome 72 getestet und arbeite immer noch gut für mich.
Janaka Dombawela
@ JanakaDombawela Was ich gesagt habe: Das Verschieben eines neuen Tabs, der ein Problem verursachen würde, ist falsch. Sie können jedoch sehen, dass das Ereignis onunload in diesem Beispiel selbst mit jQuery 1.9.1 und jQuery 1.8.3 nicht ordnungsgemäß ausgelöst wird. onunload ist unzuverlässig. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen
3

Hier ist ein allgemeinerer Ansatz. Anstatt zu verhindern, dass der Browser einen Bildlauf durchführt (oder nach oben springt, wie es aussehen würde), stelle ich einfach die vorherige Position auf der Seite wieder her. Dh ich zeichne den aktuellen y-Offset der Seite in localStorage auf und scrolle zu dieser Position, sobald die Seite geladen wurde.

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
quelle
2

Sie können einfach ein # am Ende einfügen, damit die Seite oben geladen wird.

Funktioniert auf allen Browsern, Mobilgeräten und Desktops, weil es so einfach ist.

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

});

// Dies lädt die Seite mit einem # am Ende.

Daut
quelle
Wenn ich dies direkt auf meinem Server versuche, funktioniert es wie Magie. Aber mein CMS gibt mir einen Markup-Fehler. Ich kann nicht herausfinden, was das ist.
Alice
1
Wenn Sie WordPress verwenden, ändern Sie das $ für jQuery
Herzling
1

Das funktioniert bei mir.

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });
Alex hat Spaß
quelle
-2

Du solltest in der Lage sein zu.

Überprüfen Sie beim Laden, ob window.location.hashein Wert vorhanden ist. Wenn dies der Fall ist, greifen Sie auf das Element mit einer ID zu, die dem Hashwert entspricht. Suchen Sie die Position des Elements (rekursive Aufrufe von offsetTop / offsetLeft) und übergeben Sie diese Werte an die window.scrollTo(x, y)Methode.

Dies sollte die Seite zum gewünschten Element scrollen.

nikmd23
quelle
3
Dies hindert die Browser nicht daran, automatisch zu scrollen. Darum geht es in dieser Frage.
Haralan Dobrev