Signatur
Beschreibung
Die Eigenschaft height von window.visualViewport gibt an, wie viele CSS-Pixel des Dokuments aktuell tatsächlich sichtbar sind, also wie hoch der sichtbare Ausschnitt ist. Anders als window.innerHeight, das den Layout-Viewport beschreibt, berücksichtigt visualViewport.height auch Pinch-Zoom und auf vielen mobilen Geräten die eingeblendete Bildschirmtastatur.
Der Wert ist die Höhe des sichtbaren Bereichs ohne horizontale Scrollleiste. Beim Hineinzoomen wird er kleiner, weil weniger CSS-Pixel auf den Bildschirm passen. Grob gilt: visualViewport.height ≈ innerHeight / visualViewport.scale, abzüglich eventuell eingeblendeter Browserleisten oder Tastatur.
Typische Einsatzfälle sind das Positionieren von Toolbars, Chat-Eingabefeldern oder Dialogen direkt über der mobilen Tastatur, das Nachführen fixierter Elemente beim Pinch-Zoom sowie das Setzen einer CSS-Variable für die „echte“ sichtbare Höhe. Da sich der Wert laufend ändern kann, liest man ihn am besten im resize-Event von visualViewport neu aus.
Ist das Dokument nicht vollständig aktiv (z. B. in einem abgetrennten iframe oder einem Dokument im Back-Forward-Cache), liefert die Eigenschaft 0.
Rückgabewert
0, wenn das Dokument nicht vollständig aktiv ist.Beispiele
Sichtbare Höhe mit innerHeight vergleichen
const vv = window.visualViewport;
if (vv) {
console.log(`Layout-Viewport: ${window.innerHeight}px`);
console.log(`Visueller Viewport: ${vv.height.toFixed(1)}px`);
console.log(`Zoomfaktor: ${vv.scale}`);
} else {
console.log('VisualViewport API nicht verfügbar');
}
CSS-Variable für die echte sichtbare Höhe setzen
const setVisibleHeight = () => {
const h = window.visualViewport?.height ?? window.innerHeight;
document.documentElement.style.setProperty('--vvh', `${h}px`);
};
setVisibleHeight();
window.visualViewport?.addEventListener('resize', setVisibleHeight);
// Im CSS: .fullscreen { height: var(--vvh, 100vh); }
Eingabeleiste über der mobilen Tastatur halten
const bar = document.querySelector('#chat-input');
const vv = window.visualViewport;
const positionBar = () => {
// Abstand zwischen Unterkante des sichtbaren Bereichs und Layout-Viewport
const keyboardOffset = window.innerHeight - vv.height - vv.offsetTop;
bar.style.transform = `translateY(${-Math.max(0, keyboardOffset)}px)`;
};
vv.addEventListener('resize', positionBar);
vv.addEventListener('scroll', positionBar);
positionBar();
Erkennen, ob die Bildschirmtastatur offen ist
const vv = window.visualViewport;
const THRESHOLD = 150; // px
vv.addEventListener('resize', () => {
const keyboardOpen = window.innerHeight - vv.height * vv.scale > THRESHOLD;
document.body.classList.toggle('keyboard-open', keyboardOpen);
console.log('Tastatur offen:', keyboardOpen);
});
// Wichtig · Fallstricke
- Schreibgeschützt: Zuweisungen wie
visualViewport.height = 500werden ignoriert (im Strict Mode ohne Fehler, da es sich um einen Getter ohne Setter handelt, wird einTypeErrorgeworfen). - Nicht ganzzahlig: Der Wert kann Nachkommastellen haben – vor Vergleichen ggf. runden.
- Zoom beachten: Beim Pinch-Zoom sinkt
height, obwohl sich die Gerätegröße nicht ändert. Für Bildschirmpixel mitscalemultiplizieren. - Tastaturverhalten uneinheitlich: Auf iOS-Safari verkleinert die Bildschirmtastatur nur den visuellen Viewport; auf Android-Chrome wird je nach
interactive-widget-Angabe im<meta name="viewport">ggf. auch der Layout-Viewport (innerHeight) verkleinert. - Kompatibilität:
window.visualViewportfehlt in sehr alten Browsern (Firefox Desktop erst ab Version 91). Immer perwindow.visualViewport?.heightabsichern und aufinnerHeightzurückfallen. - Performance:
resize/scrollfeuern beim Zoomen sehr häufig – Handler schlank halten oder überrequestAnimationFramedrosseln. - Liefert
0in nicht vollständig aktiven Dokumenten.