Signatur
Beschreibung
window.scrollY gibt an, wie weit der Inhalt des Dokuments gerade vertikal gescrollt ist, gemessen in CSS-Pixeln ab der Oberkante. Steht die Seite ganz oben, ist der Wert 0. Moderne Browser liefern einen Gleitkommawert mit Subpixel-Genauigkeit, z. B. 431.5, wenn gezoomt ist oder hochauflösende Displays verwendet werden.
Typische Einsatzfälle sind „Nach oben“-Buttons, Kopfzeilen, die sich ab einer bestimmten Scrolltiefe verändern, Lesefortschrittsbalken, das Speichern und Wiederherstellen der Scrollposition und das Umrechnen von Viewport- in Dokumentkoordinaten (element.getBoundingClientRect().top + window.scrollY).
Die Eigenschaft ist schreibgeschützt. Wer die Position ändern will, nutzt window.scrollTo(), window.scrollBy() oder element.scrollIntoView(). window.pageYOffset ist ein Alias mit identischem Wert, der aus Kompatibilitätsgründen erhalten bleibt.
Wichtig: scrollY bezieht sich nur auf das Scrollen des Dokuments bzw. Viewports. Scrollt nur ein einzelner Container (z. B. ein div mit overflow: auto), bleibt scrollY unverändert – dafür gibt es element.scrollTop.
Rückgabewert
0, wenn nicht gescrollt ist; beim Overscroll/Bounce-Effekt (z. B. Safari auf iOS/macOS) kurzzeitig auch negativ möglich.Beispiele
Aktuelle Scrollposition auslesen
// Seite z. B. 250 px nach unten gescrollt
console.log(`Vertikal gescrollt: ${window.scrollY}px`);
console.log(window.scrollY === window.pageYOffset); // Alias
Kopfzeile ab 100 px Scrolltiefe verkleinern (performant mit rAF)
const header = document.querySelector('header');
let ticking = false;
const update = () => {
header.classList.toggle('is-compact', window.scrollY > 100);
ticking = false;
};
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(update);
ticking = true;
}
}, { passive: true });
Lesefortschritt in Prozent berechnen
const progressBar = document.querySelector('#progress');
const getProgress = () => {
const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
return maxScroll > 0 ? Math.min(100, (window.scrollY / maxScroll) * 100) : 100;
};
window.addEventListener('scroll', () => {
progressBar.style.width = `${getProgress().toFixed(1)}%`;
}, { passive: true });
Absolute Dokumentposition eines Elements und Scrollposition wiederherstellen
const section = document.querySelector('#kontakt');
// Viewport-Koordinate + Scrollversatz = Dokument-Koordinate
const absoluteTop = section.getBoundingClientRect().top + window.scrollY;
console.log(`#kontakt beginnt bei ${Math.round(absoluteTop)}px`);
// Position vor dem Verlassen merken und später wiederherstellen
window.addEventListener('pagehide', () => {
sessionStorage.setItem('scrollPos', String(window.scrollY));
});
const saved = Number(sessionStorage.getItem('scrollPos'));
if (saved) window.scrollTo({ top: saved, behavior: 'instant' });
// Wichtig · Fallstricke
- Schreibgeschützt:
window.scrollY = 500scrollt nicht (Zuweisung wird ignoriert bzw. überschreibt nur die Eigenschaft). Zum Scrollenwindow.scrollTo()/scrollBy()verwenden. - Gleitkommawert: Vergleiche wie
window.scrollY === maxScrollkönnen wegen Subpixel-Werten fehlschlagen – besser mit Toleranz prüfen, z. B.Math.abs(a - b) < 1. - Negative Werte: Beim elastischen Overscroll (Safari) kann
scrollYkurzzeitig negativ oder größer als der maximale Wert sein; ggf. mitMath.max(0, …)begrenzen. - Layout-Neuberechnung: Das Lesen von
scrollYkann bei zuvor geänderten Styles einen synchronen Reflow erzwingen. Inscroll-Handlern Lese- und Schreibzugriffe trennen und mitrequestAnimationFramedrosseln; Listener als{ passive: true }registrieren. Für Sichtbarkeitsprüfungen istIntersectionObservermeist effizienter. - Container-Scrolling: Scrollt nicht das Dokument, sondern ein inneres Element, bleibt
scrollYbei0– dannelement.scrollTopnutzen. - Kompatibilität: In allen modernen Browsern verfügbar. Der Internet Explorer kennt nur
pageYOffset(ab IE9) bzw.document.documentElement.scrollTop. In Node.js existiertwindownicht – bei SSR vorhertypeof window !== 'undefined'prüfen.