Ist es möglich, das Standardverhalten beim Scrollen des Dokuments zu verhindern, wenn ein Popstate-Ereignis auftritt?
Unsere Website verwendet jQuery-animiertes Scrollen und History.js. Statusänderungen sollten den Benutzer über Pushstate oder Popstate zu verschiedenen Bereichen der Seite führen. Das Problem ist, dass der Browser die Bildlaufposition des vorherigen Status automatisch wiederherstellt, wenn ein Popstate-Ereignis auftritt.
Ich habe versucht, ein Containerelement zu verwenden, das auf 100% Breite und Höhe des Dokuments eingestellt ist, und den Inhalt in diesem Container zu scrollen. Das Problem dabei ist, dass es nicht annähernd so reibungslos zu sein scheint wie das Scrollen des Dokuments. vor allem, wenn Sie viel CSS3 wie Box-Shadows und Farbverläufe verwenden.
Ich habe auch versucht, die Bildlaufposition des Dokuments während eines vom Benutzer initiierten Bildlaufs zu speichern und wiederherzustellen, nachdem der Browser die Seite gescrollt hat (im Popstate). Dies funktioniert in Firefox 12 einwandfrei, in Chrome 19 tritt jedoch ein Flimmern auf, da die Seite gescrollt und wiederhergestellt wird. Ich gehe davon aus, dass dies mit einer Verzögerung zwischen dem Bildlauf und dem ausgelösten Bildlaufereignis zu tun hat (bei dem die Bildlaufposition wiederhergestellt wird).
Firefox scrollt die Seite (und löst das Bildlaufereignis aus), bevor Popstate ausgelöst wird und Chrome zuerst Popstate auslöst und dann das Dokument scrollt.
Alle Websites, die ich gesehen habe und die die Verlaufs-API verwenden, verwenden entweder eine ähnliche Lösung wie oben oder ignorieren einfach die Änderung der Bildlaufposition, wenn ein Benutzer vor / zurück geht (z. B. GitHub).
Ist es möglich zu verhindern, dass das Dokument bei Popstate-Ereignissen überhaupt gescrollt wird?
quelle
document.body.clientHeight
aber ich habe nicht gesehen, dass es in allen Browsern funktioniert.Antworten:
( Angekündigt von Google am 2. September 2015)
Browserunterstützung:
Chrome: unterstützt (seit 46)
Firefox: unterstützt (seit 46)
IE / Edge: nicht unterstützt, um Unterstützung bitten (dann Link im Kommentar hinterlassen)
Oper: unterstützt (seit 33)
Safari: unterstützt
Weitere Informationen finden Sie unter Browserkompatibilität auf MDN .
quelle
history.scrollRestoration && history.scrollRestoration = 'manual';
oder sogarvar sr = 'scrollRestoration'; history[sr] && history[sr] = 'manual';
Dies ist seit mehr als einem Jahr ein gemeldetes Problem mit dem Mozilla-Entwicklerkern . Leider hat sich das Ticket nicht wirklich weiterentwickelt. Ich denke, Chrome ist dasselbe: Es gibt keine zuverlässige Möglichkeit, die
onpopstate
Bildlaufposition über js zu ändern, da es sich um ein natives Browserverhalten handelt.Es gibt jedoch Hoffnung für die Zukunft, wenn Sie sich die HTML5-Verlaufsspezifikation ansehen , die ausdrücklich wünscht, dass die Bildlaufposition auf dem Statusobjekt dargestellt wird:
Dies und wenn Sie die oben erwähnten Kommentare zum Mozilla-Ticket lesen, gibt dies einen Hinweis darauf, dass es möglich ist, dass die Bildlaufposition in naher Zukunft nicht mehr wiederhergestellt wird
onpopstate
, zumindest für BenutzerpushState
.Leider wird bis dahin die Bildlaufposition gespeichert, wenn sie
pushState
verwendet wird, und ersetztreplaceState
nicht die Bildlaufposition. Andernfalls wäre es ziemlich einfach, und Sie könntenreplaceState
die aktuelle Bildlaufposition jedes Mal festlegen, wenn der Benutzer die Seite gescrollt hat (mit einem vorsichtigen Onscroll-Handler).Leider gibt die HTML5-Spezifikation auch nicht an, wann genau das
popstate
Ereignis ausgelöst werden muss, sondern nur: «wird in bestimmten Fällen ausgelöst, wenn zu einem Sitzungsverlaufseintrag navigiert», was nicht eindeutig angibt, ob es vorher oder nachher ist; Wenn es immer vorher war, wäre eine Lösung mit der Behandlung des Scroll-Ereignisses möglich, das nach dem Popstate auftritt.Scroll-Ereignis abbrechen?
Darüber hinaus wäre es auch einfach, wenn das Bildlaufereignis stornierbar wäre, was es nicht ist. Wenn dies der Fall wäre, könnten Sie einfach das erste Bildlaufereignis einer Serie abbrechen (Benutzer-Bildlaufereignisse sind wie Lemminge, sie kommen in Dutzenden vor, während das durch die Neupositionierung des Verlaufs ausgelöste Bildlaufereignis ein einzelnes ist), und es wäre in Ordnung.
Derzeit gibt es keine Lösung
Soweit ich sehe, würde ich vorerst nur empfehlen, auf die vollständige Implementierung der HTML5-Spezifikation zu warten und in diesem Fall mit dem Browserverhalten zu rollen. Das bedeutet: Animieren Sie das Scrollen, wenn der Browser dies zulässt und lassen Sie den Browser die Seite neu positionieren, wenn ein Verlaufsereignis vorliegt. Das einzige, was Sie in Bezug auf die Position beeinflussen können, ist, dass Sie verwenden,
pushState
wenn die Seite in einer guten Position positioniert ist, zu der Sie zurückkehren können. Jede andere Lösung muss entweder Fehler aufweisen oder zu browserspezifisch sein oder beides.quelle
Sie müssen hier einen schrecklichen Browser verwenden, der schnüffelt. Für Firefox würde ich mich für Ihre Lösung entscheiden, die Bildlaufposition zu speichern und wiederherzustellen.
Ich dachte, ich hätte eine gute Webkit-Lösung basierend auf Ihrer Beschreibung, aber ich habe es gerade in Chrome 21 versucht, und es scheint, dass Chrome zuerst einen Bildlauf durchführt, dann das Popstate-Ereignis und dann das Bildlauf-Ereignis auslöst. Aber als Referenz habe ich mir Folgendes ausgedacht:
Schwarze Magie, wie das Vorgeben, dass die Seite durch Verschieben eines
absolute
positionierten Elements gescrollt wird, wird auch durch die Neulackiergeschwindigkeit des Bildschirms ausgeschlossen.Ich bin mir also zu 99% sicher, dass die Antwort lautet, dass Sie dies nicht können, und dass Sie einen der Kompromisse eingehen müssen, die Sie in der Frage erwähnt haben. Beide Browser scrollen, bevor JavaScript etwas darüber weiß, sodass JavaScript erst nach dem Ereignis reagieren kann. Der einzige Unterschied besteht darin, dass Firefox den Bildschirm erst nach dem Auslösen von Javascript malt. Deshalb gibt es in Firefox eine praktikable Lösung, in WebKit jedoch nicht.
quelle
Jetzt können Sie tun
und dies sollte das Scrollen des Browsers verhindern. Dies funktioniert derzeit nur in Chrome 46 und höher, aber es scheint, dass Firefox plant, es auch zu unterstützen
quelle
Die Lösung besteht darin
position: fixed
,top
die Bildlaufposition der Seite zu verwenden und anzugeben .Hier ist ein Beispiel:
Ja, Sie erhalten stattdessen eine flackernde Bildlaufleiste, aber es ist weniger böse.
quelle
Das folgende Update sollte in allen Browsern funktionieren.
Sie können die Bildlaufposition beim Entladen auf 0 setzen. Sie können über diese Veranstaltung hier lesen: https://developer.mozilla.org/en-US/docs/Web/Events/unload . Im Wesentlichen wird das Entladeereignis unmittelbar vor dem Verlassen der Seite ausgelöst.
Wenn Sie beim Entladen scrollPosition auf 0 setzen, bedeutet dies, dass beim Verlassen der Seite mit einem festgelegten pushState die scrollPosition auf 0 gesetzt wird. Wenn Sie durch Aktualisieren oder Zurückdrücken zu dieser Seite zurückkehren, wird kein automatischer Bildlauf durchgeführt.
quelle
Das Einstellen von scrollRestoration auf manuell hat bei mir nicht funktioniert. Hier ist meine Lösung.
quelle
Erstellen Sie irgendwo oben auf der Seite ein 'span'-Element und konzentrieren Sie sich beim Laden darauf. Der Browser blättert zum fokussierten Element. Ich verstehe, dass dies eine Problemumgehung ist und der Fokus auf "span" nicht in allen Browsern funktioniert (uhmmm .. Safari). Hoffe das hilft.
quelle
Folgendes habe ich auf einer Site implementiert, auf der die Bildlaufposition beim Auslösen des Postzustands auf ein bestimmtes Element fokussiert werden soll (Zurück-Schaltfläche):
Getestet und funktioniert in Firefox.
Chrome scrollt zur Position, positioniert sich dann aber wieder an der ursprünglichen Position.
quelle
Wie andere sagten, gibt es keinen wirklichen Weg, nur einen hässlichen, hackigen Weg. Das Entfernen des Scroll-Ereignis-Listeners hat bei mir nicht funktioniert. Hier ist meine hässliche Vorgehensweise:
Es funktioniert in Chrome, FF und IE (es blinkt, wenn Sie zum ersten Mal in IE zurückkehren). Verbesserungsvorschläge sind willkommen! Hoffe das hilft.
quelle
Vielleicht möchten Sie das versuchen?
quelle