Signatur
Beschreibung
currentRect gehört zur Schnittstelle LayoutShiftAttribution, die über das Array LayoutShift.sources bereitgestellt wird. Jede Attribution beschreibt ein Element, das bei einer Layout-Verschiebung seine Position geändert hat. currentRect enthält das Rechteck dieses Elements nach der Verschiebung. Das Gegenstück dazu ist previousRect mit dem Zustand vor der Verschiebung.
Die Koordinaten gelten relativ zum Viewport und werden in CSS-Pixeln angegeben. Vergleicht man currentRect mit previousRect, sieht man, wie weit und in welche Richtung sich ein Element bewegt hat. So lassen sich die Ursachen eines schlechten Cumulative Layout Shift (CLS)-Werts finden, etwa nachgeladene Bilder ohne feste Maße, eingeblendete Werbebanner oder das Nachladen von Webfonts.
Typischerweise liest man die Eigenschaft in einem PerformanceObserver mit dem Eintragstyp "layout-shift" aus. Hat ein Element den Viewport durch die Verschiebung verlassen, ist das Rechteck leer: Alle Werte (x, y, width, height) sind dann 0.
Rückgabewert
x, y, width, height, top, right, bottom und left. Es gibt die Lage des Elements im Viewport nach der Verschiebung an. Liegt das Element nicht mehr im Viewport, sind alle Werte 0.Beispiele
Verschobene Elemente mit neuer Position protokollieren
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Verschiebungen direkt nach Nutzereingaben zählen nicht zum CLS
if (entry.hadRecentInput) continue;
for (const source of entry.sources) {
const { x, y, width, height } = source.currentRect;
console.log('Element:', source.node);
console.log(`Neue Position: x=${x}, y=${y}, ${width}×${height}px`);
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Verschiebungsweg aus previousRect und currentRect berechnen
const getShiftDistance = (source) => {
const prev = source.previousRect;
const curr = source.currentRect;
return {
dx: curr.x - prev.x,
dy: curr.y - prev.y,
};
};
new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
entry.sources.forEach((source) => {
const { dx, dy } = getShiftDistance(source);
console.log(`${source.node?.nodeName ?? '(entfernt)'} verschoben um dx=${dx}px, dy=${dy}px`);
});
});
}).observe({ type: 'layout-shift', buffered: true });
Elemente erkennen, die aus dem Viewport geschoben wurden
const isEmptyRect = (rect) =>
rect.width === 0 && rect.height === 0 && rect.x === 0 && rect.y === 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
for (const source of entry.sources) {
if (isEmptyRect(source.currentRect)) {
console.warn('Element hat den Viewport verlassen:', source.node);
}
}
}
}).observe({ type: 'layout-shift', buffered: true });
Verschiebungen im Debug-Modus sichtbar machen
const highlight = ({ x, y, width, height }) => {
const box = document.createElement('div');
box.className = 'cls-debug-box'; // Styling über externes CSS
Object.assign(box.style, {
position: 'fixed',
left: `${x}px`,
top: `${y}px`,
width: `${width}px`,
height: `${height}px`,
});
document.body.append(box);
setTimeout(() => box.remove(), 2000);
};
if (PerformanceObserver.supportedEntryTypes?.includes('layout-shift')) {
new PerformanceObserver((list) => {
list.getEntries().forEach((entry) =>
entry.sources.forEach((s) => highlight(s.currentRect))
);
}).observe({ type: 'layout-shift' });
}
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die Layout Instability API gibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera). Firefox und Safari unterstützen sie nicht. Vorher prüfen, z. B. mit
PerformanceObserver.supportedEntryTypes.includes('layout-shift'). - Viewport-Koordinaten: Die Werte beziehen sich auf den Viewport, nicht auf das Dokument. Scrollt die Seite, sind die Rechtecke nicht mit Seitenkoordinaten vergleichbar. Bei Bedarf
scrollX/scrollYaddieren. - Leeres Rechteck: Wurde das Element aus dem Viewport geschoben, sind alle Werte
0. Das ist kein Fehler. - Nur eine Auswahl:
sourcesenthält höchstens fünf Attributionen pro Verschiebung, sortiert nach ihrem Einfluss. Kleinere Verursacher können fehlen. - Momentaufnahme: Das Rechteck zeigt den Zustand zum Zeitpunkt der Verschiebung. Die aktuelle Position erhält man stattdessen mit
node.getBoundingClientRect().nodekannnullsein, wenn das Element inzwischen aus dem DOM entfernt wurde. - Einträge mit
hadRecentInput === trueausfiltern, weil sie nicht in den CLS-Wert einfließen.