Signatur
Beschreibung
window.scrollTo() scrollt das Dokument zu einer absoluten Pixel-Position. Die Koordinaten beziehen sich auf die linke obere Ecke des Dokuments: scrollTo(0, 0) springt also immer ganz nach oben, egal wo man gerade steht. Im Gegensatz dazu scrollt scrollBy() relativ zur aktuellen Position.
Es gibt zwei Aufrufformen: mit zwei Zahlen (x, y) oder mit einem Options-Objekt { top, left, behavior }. Nur über das Options-Objekt lässt sich per behavior: "smooth" weich scrollen. Fehlt top oder left im Objekt, bleibt die jeweilige Achse unverändert – so kann man gezielt nur vertikal scrollen.
Typische Einsätze sind „Nach oben“-Schaltflächen, das Wiederherstellen einer gespeicherten Scroll-Position (etwa in Single-Page-Apps nach einem Routenwechsel) oder das Scrollen zu einer berechneten Position, z. B. zu einem Element abzüglich der Höhe eines fixierten Headers. window.scroll() ist ein funktionsgleicher Alias.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $x-coord | number | Horizontale Zielposition in CSS-Pixeln (entspricht dem späteren window.scrollX). Nur in der Zwei-Argument-Form. |
|
| $y-coord | number | Vertikale Zielposition in CSS-Pixeln (entspricht dem späteren window.scrollY). Nur in der Zwei-Argument-Form. |
|
| $options | ScrollToOptions | {} | Objekt als Alternative zu den Koordinaten:
|
Beispiele
„Nach oben“-Schaltfläche mit weichem Scrollen
const button = document.querySelector('#nach-oben');
button.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// Schaltfläche erst ab 400 px Scroll-Tiefe anzeigen
window.addEventListener('scroll', () => {
button.hidden = window.scrollY < 400;
}, { passive: true });
Zu einem Element scrollen, fixierten Header berücksichtigen
const scrollZuAbschnitt = (selector, headerHoehe = 80) => {
const ziel = document.querySelector(selector);
if (!ziel) return;
// getBoundingClientRect() ist relativ zum Viewport → aktuelle Scroll-Position addieren
const top = ziel.getBoundingClientRect().top + window.scrollY - headerHoehe;
window.scrollTo({ top, behavior: 'smooth' });
};
scrollZuAbschnitt('#kontakt');
Scroll-Position speichern und wiederherstellen
// Beim Verlassen der Seite merken
window.addEventListener('pagehide', () => {
sessionStorage.setItem('scrollPos', JSON.stringify({ x: window.scrollX, y: window.scrollY }));
});
// Beim Laden wiederherstellen (sofort, ohne Animation)
window.addEventListener('load', () => {
const gespeichert = sessionStorage.getItem('scrollPos');
if (gespeichert) {
const { x, y } = JSON.parse(gespeichert);
window.scrollTo(x, y);
console.log(`Wiederhergestellt: ${x}/${y}`);
}
});
Auf das Ende des weichen Scrollens warten
const scrollToAsync = (top) => new Promise((resolve) => {
if (Math.abs(window.scrollY - top) < 1) return resolve();
window.addEventListener('scrollend', resolve, { once: true });
window.scrollTo({ top, behavior: 'smooth' });
});
await scrollToAsync(0);
console.log('Oben angekommen');
// Wichtig · Fallstricke
- Absolut vs. relativ:
scrollTo()setzt eine absolute Position; für „noch 100 px weiter“ istscrollBy()gedacht. - Werte werden begrenzt: Negative oder zu große Koordinaten werden stillschweigend auf den gültigen Bereich (0 bis maximale Scroll-Tiefe) gekürzt – es gibt keinen Fehler.
- Kein Promise: Bei
behavior: "smooth"kehrt der Aufruf sofort zurück. Das Ereignisscrollendist erst seit 2023 verbreitet (Safari erst ab 18.x) – ggf. per Timeout oderscroll-Ereignis absichern. - Smooth-Unterstützung: Sehr alte Browser (Safari < 15.4, IE) ignorieren
behaviorbzw. das Options-Objekt; IE unterstützt nur die Zwei-Argument-Form. - Barrierefreiheit: Nutzer mit
prefers-reduced-motion: reducesollten keine Animation bekommen – prüfen permatchMedia('(prefers-reduced-motion: reduce)'). - Anderer Scroll-Container: Scrollt nicht
html/body, sondern ein Element mitoverflow: auto, hatwindow.scrollTo()keine Wirkung – dannelement.scrollTo()verwenden. - Ein zu früher Aufruf (bevor Bilder/Schriften geladen sind) kann zu falschen Zielpositionen führen, weil sich das Layout noch verschiebt. Außerdem kann
history.scrollRestoration = 'manual'nötig sein, damit der Browser die eigene Wiederherstellung nicht überschreibt.