Langsam Scrollen
als Präsentation ▻Das Ziel dieser Übung ist: Wenn ein “interner” Link, ein Link zu einer Textmarke in derselben Seite, angeklickt wird, dann soll das Fenster langsam zur Zielposition scrollen, so dass man besser nachvollziehen kann dass der Link innerhalb der Seite erfolgte.
▻Interne Links mit Hash
Links innerhalb einer Seite können auf jede id
in der Seite verweisen.
In folgendem Beispiel verweist der dritte Link im Navigationsmenü
auf die <section>
mit der id order
:
Html Code Navigationsmenü mit internen Links
<nav> <ul> <li><a href="#hero">Home</a></li> <li><a href="#menu">Speisekarte</a></li> <li><a href="#order">Online Bestellen</a></li> <li><a href="#guest">Gästebuch</a></li> <li><a href="#newsletter">Newsletter</a></li> <li><a href="#contact">Kontakt</a></li> </ul> </nav> .... <section id="order"> .... <footer id="contact">
Wird so ein interner Link angeklick, erfolgt die neue Darstellung der Seite blitzschnell. Es ist schwer zu erkennen, dass man sich nun nicht auf einer neuen, anderern Seite befindet, sondern einfach nur weiter unten auf derselben Seite.
Die Lösung: langsam scrollen.
▻Mit CSS: scroll-behaviour
Seit Jänner 2020 unterstützt auch Edge die css property scroll-behaviour:
html { scroll-behavior: smooth; }
Damit ist die Aufgabe erledigt.
▻Mit Javascript
Diese Erklärung ist nicht mehr nötig, die Lösung mit CSS ist besser.
▻Normalen Link verhindern
Als ersten Schritt setzen wir einen EventListener
um das click
event
abzufangen, und mit preventDefault
das “normale” Verhalten des Links zu
unterbinden.
// let l = .... ein link in der Seite ... l.addEventListener('click', scroll_to_link); function scroll_to_link(ev) { console.log(`link geclickt. wird ignoriert!`); ev.preventDefault(); }
Damit sind die Links erst mal kaputt:
Im Event-Handler ist die Variable this
gesetzt: sie verweist
auf das angeklickte Element der Webseite. In diesem Fall ist das
immer ein a
-Tag. Mit der Methode href
könnte man die vollständige
URL auslesen, auf die der Link verweist. Wir sind aber nur am letzten
Teil der URL interessiert. Den kann man mit der Methode hash
auslesen:
let hash = this.hash; // z.B. '#order'
Zum Element hin Scrollen
Die DOM-Methode scrollIntoView erledigt das eigentliche Scrollen zum Element hin.
document.querySelector(hash).scrollIntoView({ behavior: "smooth" });
Kompatibilität
Die Funktion scrollIntoView wird nicht von allen Browsern implementiert. Woher kann ich das wissen? Wie kann man damit umgehen?
Ein guter Startpunkt für diese Fragen ist die Webseite “can i use”. Hier kann man für verschiedene HTML, CSS, JavaScript Features nachlesen welche Browser dieses Feature unterstützen. In diesem Fall unter https://caniuse.com/#search=scrollintoview.
Bei caniuse lernen wir: die Option “smooth” ist in Safari und IE nicht implementiert. Unter dem Tab “Resourcse” liefert die Seite auch gleich eine Lösung: Ein polyfill - eine Javascript Libary die die fehlende Funktionalität implementiert: smooth scroll behavior polyfill.
▻Der Browser funktioniert nicht mehr
Da wir mit event.preventDefault
die “normale” Behandlung des Links verhindert
haben, wird auch die URL nicht mehr korrekt gesetzt und im Browser angezeigt.
Das heisst wenn ich den Link zum Gästebuch anklicke, dann zeigt der Browser
danach nicht korrekt http://users.multimediatechnology.at/~fhs0000/pizza/#guest
an,
sondern weiterhin die URL http://users.multimediatechnology.at/~fhs0000/pizza/
.
Ohne Korrekte URL funktioniert die Navigation nicht wie erwartet:
z.B. Lisa liest einen Eintrag im Gästebuch, findet ihn witzig, und schickt den Link weiter an Bart. Wenn Bart die URL verwendet, landet er aber ganz oben auf der Seite, und versteht nicht was Lisa so witzig findet.
z.B. Homer betrachtet gerade seinen Kontostand im Online-Banking und ist deprimiert. Um seine Laune zu heben will er eine Pizza bestellen, und tippt die URL der Pizzaria ein. Im Navigationsmenü klickt auf “Speisekarte”, sucht sich eine Pizza aus, und klickt danach auf “Online Bestellen”. Er hat aber schon wieder vergessen welche Pizza er wollte, und verwendet den “Zurück”-Button des Browsers um zur Speisekarte zurück zu gehen. Statt dessen landet er aber wieder im Online-Banking. Denn für den “Zurück”-Button zählt eine Seite nur, wenn sie eine eigene URL hat. Da die Klicks im Navigationsmenü der Pizzaria-Seite die URL nicht verändert haben zählen sie nicht.
Wenn wir die erwartete Funktionsweise des Browsers wiederherstellen wollen, müssen wir die korrekte URL setzen.
▻Korrekte URL setzen
Welche Seiten in welcher Reihenfolge angesurft wurden ist im Browser gespeichert,
und in Javascript durch das window.history
Objekt dargestellt. Auf dieses
Objekt hat man aber nicht vollen Zugriff: sonst könnte ja jede Webseite
die BesucherInnen ausspionieren und herausfinden wo sie vorher waren.
Einige wenige Manipulationen
des History Objekts sind erlaubt: mit den Methoden back()
, forward()
und go()
kann
man von Javascript aus die “Vorwärts” und “Zurück” Buttons bedienen.
Mit pushState()
und replaceState()
kann man der History einen neuen Eintrag
hinzufügen. Ganz so, als würde eine neue Seite geladen. Aber: es wird nicht wirklich
eine neue Seite geladen, das HTML-Dokument und der Zustand des Javascript-Programmes
bleiben genau gleich. Alle Variablen enthalte dieselben Werte, alle Funktionen sind noch definiert.
Für unser Beispiel brauchen wir nur das dritte Argument von pushState
: die neue URL
die angezeigt werden soll. Es reicht eine relative URL, in unserem Fall nur das Hash-Zeichen
und die id.
Das erste Argument von pushState muss ein Objekt sein (es reicht ein leeres Objekt), das zweite Argument muss ein String sein (es reicht ein leerer String), das dritte Argument ist die relative URL:
window.history.pushState({}, "", hash);
Fertig
Wenn wir alles richtig programmiert haben funktioniert nun das Navigations-Menü wieder: bei klick wird langsam zum entsprechenden Teil der seite gescrollt, und die URLs ändern sich.
▻