Start · Sprachen · JavaScript · Referenz · ResizeObserver

ResizeObserver

Schnittstelle

Beobachtet Größenänderungen des Inhalts- oder Rahmenbereichs von Elementen bzw. der Bounding-Box von SVG-Elementen und ruft dann einen Callback auf.

seit JavaScript Baseline: alle modernen Browser (seit 2020) Kategorie: webapi

Signatur

interface ResizeObserver

Beschreibung

ResizeObserver meldet, wenn sich die Abmessungen eines Element (Inhalts- oder Rahmenbereich) oder die Bounding-Box eines SVGElement ändern. Anders als das resize-Event von window reagiert der Observer auf jede Größenänderung eines einzelnen Elements, egal ob sie durch das Ändern der Fenstergröße, per CSS, durch neuen Inhalt, Flex-/Grid-Layout oder JavaScript entsteht.

Typische Einsatzfälle sind komponentenbasierte, responsive Layouts (Element-Queries in JavaScript), das Neuzeichnen von <canvas>-Inhalten oder Diagrammen bei neuer Containergröße, virtuelle Listen, automatisch wachsende Textfelder und das Nachführen von Tooltips oder Overlays.

Der Konstruktor new ResizeObserver(callback) erwartet eine Callback-Funktion, die ein Array von ResizeObserverEntry-Objekten und den Observer selbst erhält. Die Methoden sind:

  • observe(target, options) – beginnt die Beobachtung eines Elements; options.box legt fest, welche Box gemessen wird ("content-box", "border-box", "device-pixel-content-box").
  • unobserve(target) – beendet die Beobachtung eines bestimmten Elements.
  • disconnect() – beendet die Beobachtung aller Elemente.

Die Callbacks laufen nach dem Layout und vor dem Zeichnen des Frames. Jedes ResizeObserverEntry bietet target, contentRect (älter, DOMRectReadOnly) sowie die moderneren Arrays contentBoxSize, borderBoxSize und devicePixelContentBoxSize mit inlineSize und blockSize.

Parameter

Name Typ Default Beschreibung
$callback Pflicht (entries: ResizeObserverEntry[], observer: ResizeObserver) => void Wird bei Größenänderungen aufgerufen. Einmal auch direkt nach observe() mit der Anfangsgröße. entries enthält ein Objekt pro Element, dessen Größe sich geändert hat.
$target Pflicht Element | SVGElement Parameter von observe()/unobserve(): das zu beobachtende Element.
$options.box "content-box" | "border-box" | "device-pixel-content-box" "content-box" Parameter von observe(): Welches Box-Modell gemessen wird. device-pixel-content-box liefert die Größe in echten Gerätepixeln, ideal für Canvas.

Rückgabewert

Typ
ResizeObserver
Beschreibung
Der Konstruktor liefert eine neue ResizeObserver-Instanz. observe(), unobserve() und disconnect() geben undefined zurück.

Beispiele

Observer erzeugen und Größe protokollieren

const box = document.querySelector('#panel');

const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    // contentBoxSize ist ein Array (z. B. für mehrspaltige Fragmente)
    const { inlineSize, blockSize } = entry.contentBoxSize[0];
    console.log(`Breite: ${Math.round(inlineSize)}px, Höhe: ${Math.round(blockSize)}px`);
  }
});

observer.observe(box);
Breite: 320px, Höhe: 180px

Komponente per CSS-Klasse an Containerbreite anpassen

const cards = document.querySelectorAll('.card');

const ro = new ResizeObserver((entries) => {
  for (const { target, borderBoxSize } of entries) {
    const width = borderBoxSize[0].inlineSize;
    target.classList.toggle('card--compact', width < 400);
    target.classList.toggle('card--wide', width >= 800);
  }
});

cards.forEach((card) => ro.observe(card, { box: 'border-box' }));

Canvas scharf in Gerätepixeln neu zeichnen

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

const draw = () => {
  ctx.fillStyle = '#0a7';
  ctx.fillRect(0, 0, canvas.width, canvas.height / 2);
};

const ro = new ResizeObserver(([entry]) => {
  // Fallback, falls device-pixel-content-box nicht unterstützt wird
  const size = entry.devicePixelContentBoxSize?.[0];
  canvas.width = size ? size.inlineSize : Math.round(entry.contentRect.width * devicePixelRatio);
  canvas.height = size ? size.blockSize : Math.round(entry.contentRect.height * devicePixelRatio);
  draw();
});

try {
  ro.observe(canvas, { box: 'device-pixel-content-box' });
} catch {
  ro.observe(canvas);
}

Beobachtung beenden (z. B. beim Entfernen einer Komponente)

const el = document.querySelector('#chart');
const ro = new ResizeObserver(([entry]) => {
  console.log('Neue Breite:', entry.contentRect.width);
});
ro.observe(el);

// Später: nur dieses Element nicht mehr beobachten
ro.unobserve(el);

// Oder alle Beobachtungen auf einmal beenden
ro.disconnect();

// Wichtig · Fallstricke

  • Endlosschleifen: Wenn Sie im Callback die Größe des beobachteten Elements ändern, wird ein weiterer Durchlauf ausgelöst. Der Browser bricht das ab und meldet ResizeObserver loop completed with undelivered notifications (bzw. loop limit exceeded) als Fehler an window.onerror. Größenänderungen nach Möglichkeit an Kind-Elementen vornehmen oder per requestAnimationFrame verschieben.
  • Der Callback wird sofort nach observe() einmal mit der Anfangsgröße aufgerufen, außerdem wenn ein Element eingefügt, entfernt oder auf display: none gesetzt wird (Größe 0).
  • Reine Positionsänderungen oder transform (z. B. scale()) lösen keine Meldung aus, da sich die Layoutgröße nicht ändert.
  • contentBoxSize/borderBoxSize sind Arrays; ältere Firefox-Versionen (vor 92) lieferten ein einzelnes Objekt. contentRect ist aus Kompatibilitätsgründen noch vorhanden, gilt aber als veraltet.
  • device-pixel-content-box wird von Safari erst seit Version 17 unterstützt – ggf. mit try/catch absichern.
  • inlineSize/blockSize hängen vom Schreibmodus ab: bei vertikaler Schrift entspricht inlineSize der Höhe.
  • Für die Performance ist ein einziger Observer für viele Elemente günstiger als viele einzelne Instanzen. Nicht mehr benötigte Observer mit disconnect() beenden, um Speicherlecks in SPAs zu vermeiden.
  • Für reine Layout-Anpassungen ohne JavaScript sind CSS-Container-Queries (@container) oft die bessere Wahl.