Signatur
Beschreibung
Die Eigenschaft node eines LayoutShiftAttribution-Objekts gibt das DOM-Element (genauer: den Node) zurück, das bei einem Layout-Shift seine Position verändert hat. Mehrere solcher Attributionen findest du im Array LayoutShift.sources. Dieses Array gehört zu einem Performance-Eintrag vom Typ "layout-shift", den du mit einem PerformanceObserver erhältst.
Gebraucht wird die Eigenschaft vor allem, um den Cumulative Layout Shift (CLS) zu debuggen, also eine der Core Web Vitals. Der CLS-Wert allein zeigt nur, wie stark sich das Layout verschoben hat. Über node erfährst du, welche Elemente sich bewegt haben, zum Beispiel ein Banner, das nachträglich eingefügt wird, oder ein Bild ohne feste Abmessungen.
Der Browser liefert höchstens fünf Quellen pro Layout-Shift, und zwar die mit der größten Auswirkung. Oft ist node nicht das Element, das die Verschiebung verursacht hat, sondern ein Element, das dadurch verschoben wurde. Um die eigentliche Ursache zu finden, lohnt sich meist ein Blick auf das vorherige Geschwister- oder das Elternelement.
Rückgabewert
Node, meist ein Element, manchmal auch ein Textknoten. null, wenn der Knoten inzwischen aus dem DOM entfernt wurde oder der Browser ihn nicht preisgibt.Beispiele
Verschobene Elemente in der Konsole ausgeben
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Verschiebungen direkt nach einer Nutzereingabe zählen nicht zum CLS
if (entry.hadRecentInput) continue;
for (const source of entry.sources) {
console.log('Verschoben:', source.node, 'Wert:', entry.value.toFixed(4));
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Lesbaren Selektor für das Monitoring erzeugen
const describeNode = (node) => {
if (!node) return '(entfernt)';
if (node.nodeType !== Node.ELEMENT_NODE) {
return `#text in ${describeNode(node.parentElement)}`;
}
const id = node.id ? `#${node.id}` : '';
const cls = node.classList.length ? `.${[...node.classList].join('.')}` : '';
return `${node.tagName.toLowerCase()}${id}${cls}`;
};
new PerformanceObserver((list) => {
const report = list.getEntries()
.filter((e) => !e.hadRecentInput)
.flatMap((e) => e.sources.map((s) => ({
selector: describeNode(s.node),
value: e.value
})));
if (report.length) {
// An einen Analytics-Endpunkt senden
navigator.sendBeacon('/cls-report', JSON.stringify(report));
}
}).observe({ type: 'layout-shift', buffered: true });
Verschobene Elemente zum Debuggen hervorheben
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
for (const { node } of entry.sources) {
if (node instanceof HTMLElement) {
node.style.outline = '3px solid red';
setTimeout(() => { node.style.outline = ''; }, 2000);
}
}
}
}).observe({ type: 'layout-shift', buffered: true });
// Wichtig · Fallstricke
- Browser-Unterstützung: Die Layout Instability API gibt es nur in Chromium-basierten Browsern. Prüfe die Unterstützung vorher, zum Beispiel mit
PerformanceObserver.supportedEntryTypes.includes('layout-shift'). nodekannnullsein, etwa wenn das Element nach der Verschiebung aus dem DOM entfernt wurde. Prüfe den Wert deshalb immer, bevor du darauf zugreifst.- Es kann auch ein Textknoten zurückkommen, der keine Eigenschaften wie
idoderclassListhat. Frage vorhernodeTypeab oder verwendeinstanceof Element. - Das verschobene Element ist nicht unbedingt die Ursache der Verschiebung. Häufig liegt die Ursache in einem Element davor, zum Beispiel einem nachgeladenen Werbeblock.
- Speichere keine dauerhaften Referenzen auf die Knoten in globalen Arrays. Sonst kann der Speicher entfernter DOM-Teile nicht freigegeben werden, und es entstehen Speicherlecks. Wandle die Knoten für Berichte besser gleich in Selektor-Strings um.
- Pro
LayoutShift-Eintrag werden höchstens fünf Quellen gemeldet.