Signatur
Beschreibung
Das resize-Ereignis von VisualViewport feuert immer dann, wenn sich die Breite oder Höhe des visuellen Viewports ändert. Der visuelle Viewport ist der tatsächlich sichtbare Ausschnitt der Seite. Er kann kleiner sein als der Layout-Viewport, z. B. wenn der Nutzer per Pinch hineinzoomt oder auf Mobilgeräten die Bildschirmtastatur eingeblendet wird.
Das Ereignis wird über window.visualViewport.addEventListener("resize", handler) oder über die Eigenschaft window.visualViewport.onresize registriert. Der Handler bekommt ein einfaches Event-Objekt ohne Größenangaben. Die aktuellen Werte liest man direkt aus visualViewport.width, height, scale, offsetTop und offsetLeft.
Typische Einsatzfälle sind: fixierte Werkzeugleisten oberhalb der Bildschirmtastatur halten, schwebende Elemente beim Zoomen an ihrer Position lassen oder Layouts an die wirklich sichtbare Fläche anpassen. Anders als window-resize reagiert dieses Ereignis auch auf Zoom und Tastatur, die den Layout-Viewport nicht verändern.
Verschiebt sich der visuelle Viewport nur, ohne seine Größe zu ändern, feuert stattdessen das Ereignis scroll von VisualViewport. Für eine vollständige Nachführung sollte man meist beide Ereignisse abonnieren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "resize". |
|
| $handler Pflicht | (event: Event) => void | Callback-Funktion. Sie erhält ein allgemeines Event; event.target ist das VisualViewport-Objekt. |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Einstellungen wie once, passive oder signal (zum Entfernen über einen AbortController). |
Rückgabewert
addEventListener gibt nichts zurück. Die neuen Maße liest man im Handler aus visualViewport aus.Beispiele
Größenänderung protokollieren (addEventListener)
const vv = window.visualViewport;
const logSize = () => {
console.log(`Sichtbar: ${Math.round(vv.width)}×${Math.round(vv.height)} px, Zoom: ${vv.scale.toFixed(2)}`);
};
if (vv) {
vv.addEventListener('resize', logSize);
logSize();
}
Werkzeugleiste über der Bildschirmtastatur halten
const toolbar = document.querySelector('#toolbar');
const vv = window.visualViewport;
const positionToolbar = () => {
// Abstand zwischen Unterkante des Layout-Viewports und Unterkante des sichtbaren Bereichs
const offsetBottom = window.innerHeight - (vv.height + vv.offsetTop);
toolbar.style.transform = `translateY(${-Math.max(0, offsetBottom)}px)`;
};
vv.addEventListener('resize', positionToolbar);
vv.addEventListener('scroll', positionToolbar);
positionToolbar();
on-Property und Entfernen per AbortController
const vv = window.visualViewport;
// Variante 1: on-Property (überschreibt einen vorherigen Handler)
vv.onresize = () => console.log('Neue Höhe:', vv.height);
// Variante 2: Listener mit AbortController wieder entfernen
const controller = new AbortController();
vv.addEventListener('resize', () => {
console.log('Zoomfaktor:', vv.scale);
}, { signal: controller.signal });
// Später, z. B. beim Verlassen der Ansicht:
controller.abort();
vv.onresize = null;
Handler mit requestAnimationFrame drosseln
const vv = window.visualViewport;
let scheduled = false;
const onResize = () => {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
document.documentElement.style.setProperty('--vv-height', `${vv.height}px`);
scheduled = false;
});
};
vv.addEventListener('resize', onResize, { passive: true });
// Später wieder entfernen:
// vv.removeEventListener('resize', onResize);
// Wichtig · Fallstricke
- Keine Daten im Event: Das Ereignisobjekt enthält keine Maße. Die Werte stehen in
window.visualViewportbzw.event.target. - Existenz prüfen: In älteren Browsern (z. B. Firefox vor Version 91) gibt es
window.visualViewportnicht. Vorher prüfen:if (window.visualViewport) { … }. - Tastaturverhalten unterscheidet sich je Plattform: Unter iOS Safari verkleinert die Bildschirmtastatur nur den visuellen Viewport. Unter Android Chrome wurde früher auch der Layout-Viewport verkleinert. Seit Chrome 108 geschieht das standardmäßig nicht mehr, steuerbar über
<meta name="viewport" content="interactive-widget=…">. Auf mobilen Geräten immer testen. - Hohe Auslösefrequenz: Beim Pinch-Zoom feuert das Ereignis sehr oft. Aufwendige DOM-Änderungen sollte man per
requestAnimationFramebündeln und Layout-Thrashing (abwechselndes Lesen und Schreiben von Layout-Werten) vermeiden. - Nicht mit
window-resizeverwechseln: Beim Zoomen feuertwindowkeinresize,visualViewportdagegen schon. Ändert sich nuroffsetTop/offsetLeft, kommt einscroll-Ereignis und keinresize. - Das Ereignis steigt nicht auf (kein Bubbling) und lässt sich nicht abbrechen.