Start · Sprachen · JavaScript · Referenz · VisualViewport

VisualViewport

Schnittstelle

Stellt den visuellen Viewport eines Fensters dar, also den Bereich, der gerade sichtbar ist. Berücksichtigt Pinch-Zoom und eingeblendete Bildschirmtastaturen.

seit JavaScript Baseline 2021: Chrome 61+, Edge 79+, Firefox 91+, Kategorie: webapi

Signatur

interface VisualViewport extends EventTarget

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-Pixeln
  • pageLeft / pageTop: Position relativ zum Anfang des Dokuments
  • width / height: sichtbare Größe in CSS-Pixeln
  • scale: 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

Typ
VisualViewport | null
Beschreibung
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');
}
{ breite: 390, hoehe: 844, zoom: 1, offsetTop: 0, pageTop: 0 }

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)}`);
};
Zoomfaktor: 1.75

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);
sichtbare Höhe: 512

// Wichtig · Fallstricke

  • Kompatibilität: Firefox auf dem Desktop unterstützt die API erst ab Version 91. Ältere Browser liefern undefined. Prüfe deshalb vorher mit if (window.visualViewport). Das Ereignis scrollend ist neuer und wird noch nicht überall unterstützt.
  • Werte sind Gleitkommazahlen: width, height und die Versatzwerte können Nachkommastellen haben. Runde sie bei Bedarf mit Math.round().
  • Bildlaufleisten: width und height zählen klassische Bildlaufleisten nicht mit. Die Werte können deshalb kleiner sein als innerWidth bzw. innerHeight.
  • Performance: resize und scroll feuern während einer Geste sehr oft. Bündle DOM-Änderungen mit requestAnimationFrame und nutze vorzugsweise transform statt top/left.
  • iOS Safari: Beim Öffnen der Tastatur ändert sich der Layout-Viewport oft nicht, nur der visuelle Viewport. Nur über visualViewport lässt sich die Tastaturhöhe zuverlässig ermitteln. Alternativ gibt es die neuere VirtualKeyboard-API mit eingeschränkter Unterstützung.
  • In iframes beschreibt visualViewport den Viewport des jeweiligen Frames. scale und die Versatzwerte sind dort meist neutral.