Signatur
Beschreibung
Das Interface VisualViewport gehört zur CSSOM View API und beschreibt den visuellen Viewport, also den Teil der Seite, den der Nutzer gerade tatsächlich sieht. Der Layout-Viewport ist dagegen die Fläche, an der sich position: fixed und die CSS-Einheiten vw/vh ausrichten. Sobald jemand per Pinch-Geste zoomt oder auf Mobilgeräten die Bildschirmtastatur erscheint, wird der visuelle Viewport kleiner als der Layout-Viewport und kann sich gegen ihn verschieben.
Die einzige Instanz bekommst du über window.visualViewport. Einen Konstruktor gibt es nicht. Das Objekt hat nur lesbare Eigenschaften:
offsetLeft/offsetTop: Versatz zum Layout-Viewport in CSS-PixelnpageLeft/pageTop: Position relativ zum Anfang des Dokumentswidth/height: sichtbare Größe in CSS-Pixelnscale: aktueller Pinch-Zoom-Faktor
Dazu kommen die Ereignisse resize, scroll und scrollend. Du kannst sie mit addEventListener oder über die Eigenschaften onresize, onscroll und onscrollend abonnieren.
Typische Einsatzfälle sind Werkzeugleisten, die über der Bildschirmtastatur bleiben sollen, Chat-Eingabefelder, Tooltips, die beim Zoomen an der richtigen Stelle bleiben müssen, und die Anpassung eigener Overlays an den tatsächlich sichtbaren Bereich.
Rückgabewert
window.visualViewport liefert die VisualViewport-Instanz des Fensters. Ist das Dokument nicht vollständig aktiv, zum Beispiel ein abgelöster iframe, ist der Wert null.Beispiele
Instanz abrufen und Eigenschaften lesen
const vv = window.visualViewport;
if (vv) {
console.log({
breite: vv.width,
hoehe: vv.height,
zoom: vv.scale,
offsetTop: vv.offsetTop,
pageTop: vv.pageTop
});
} else {
console.log('VisualViewport wird nicht unterstützt');
}
Werkzeugleiste über der Bildschirmtastatur halten
const toolbar = document.querySelector('#toolbar');
const vv = window.visualViewport;
const positionieren = () => {
// Abstand zwischen dem unteren Rand des sichtbaren Bereichs und dem Layout-Viewport
const abstandUnten = window.innerHeight - (vv.height + vv.offsetTop);
toolbar.style.transform = `translateY(${-Math.max(0, abstandUnten)}px)`;
};
vv.addEventListener('resize', positionieren);
vv.addEventListener('scroll', positionieren);
positionieren();
Pinch-Zoom erkennen und Overlay ausblenden (on-Property)
const overlay = document.querySelector('.hinweis');
window.visualViewport.onresize = (event) => {
const { scale } = event.target;
overlay.hidden = scale > 1.05;
console.log(`Zoomfaktor: ${scale.toFixed(2)}`);
};
Listener sauber entfernen
const vv = window.visualViewport;
const controller = new AbortController();
const protokollieren = () => console.log('sichtbare Höhe:', Math.round(vv.height));
vv.addEventListener('resize', protokollieren, { signal: controller.signal });
// später, z. B. wenn die Komponente entfernt wird:
controller.abort();
// alternativ: vv.removeEventListener('resize', protokollieren);
// Wichtig · Fallstricke
- Kompatibilität: Firefox auf dem Desktop unterstützt die API erst ab Version 91. Ältere Browser liefern
undefined. Prüfe deshalb vorher mitif (window.visualViewport). Das Ereignisscrollendist neuer und wird noch nicht überall unterstützt. - Werte sind Gleitkommazahlen:
width,heightund die Versatzwerte können Nachkommastellen haben. Runde sie bei Bedarf mitMath.round(). - Bildlaufleisten:
widthundheightzählen klassische Bildlaufleisten nicht mit. Die Werte können deshalb kleiner sein alsinnerWidthbzw.innerHeight. - Performance:
resizeundscrollfeuern während einer Geste sehr oft. Bündle DOM-Änderungen mitrequestAnimationFrameund nutze vorzugsweisetransformstatttop/left. - iOS Safari: Beim Öffnen der Tastatur ändert sich der Layout-Viewport oft nicht, nur der visuelle Viewport. Nur über
visualViewportlässt sich die Tastaturhöhe zuverlässig ermitteln. Alternativ gibt es die neuereVirtualKeyboard-API mit eingeschränkter Unterstützung. - In iframes beschreibt
visualViewportden Viewport des jeweiligen Frames.scaleund die Versatzwerte sind dort meist neutral.