Signatur
Beschreibung
Die schreibgeschützte Eigenschaft value eines LayoutShift-Eintrags liefert den Layout-Shift-Score einer einzelnen unerwarteten Layoutverschiebung. Berechnet wird er als Produkt aus Impact Fraction (wie viel vom Viewport die instabilen Elemente vor und nach der Verschiebung zusammen belegen) und Distance Fraction (größte Verschiebungsstrecke im Verhältnis zur größeren Viewport-Abmessung).
Der Wert ist die Grundlage für die Core-Web-Vitals-Kennzahl Cumulative Layout Shift (CLS). Um CLS zu berechnen, fasst man die value-Werte zu Sitzungsfenstern zusammen (maximal 5 Sekunden lang, höchstens 1 Sekunde Abstand zwischen zwei Verschiebungen) und nimmt das Fenster mit der höchsten Summe. Ein CLS von 0,1 oder weniger gilt als gut.
Einträge bekommt man über einen PerformanceObserver mit dem Typ "layout-shift". Verschiebungen, die innerhalb von 500 ms nach einer Nutzereingabe passieren, haben hadRecentInput === true. Sie gelten als erwartet und sollten bei der CLS-Berechnung weggelassen werden.
Rückgabewert
0 und 1.Beispiele
Einzelne Layoutverschiebungen protokollieren
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`Shift-Score: ${entry.value.toFixed(4)}`, entry.hadRecentInput ? '(nach Eingabe)' : '');
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Cumulative Layout Shift (CLS) mit Sitzungsfenstern berechnen
let cls = 0;
let sessionValue = 0;
let sessionEntries = [];
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Verschiebungen direkt nach Nutzereingaben ignorieren
if (entry.hadRecentInput) continue;
const first = sessionEntries[0];
const last = sessionEntries.at(-1);
// Neues Fenster, wenn > 1 s Abstand oder Fenster > 5 s
if (
sessionEntries.length &&
(entry.startTime - last.startTime > 1000 ||
entry.startTime - first.startTime > 5000)
) {
sessionValue = 0;
sessionEntries = [];
}
sessionValue += entry.value;
sessionEntries.push(entry);
if (sessionValue > cls) {
cls = sessionValue;
console.log('Aktueller CLS:', cls.toFixed(3));
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Große Verschiebungen samt Verursacher melden
const THRESHOLD = 0.05;
new PerformanceObserver((list) => {
list.getEntries()
.filter((e) => !e.hadRecentInput && e.value > THRESHOLD)
.forEach((e) => {
const nodes = e.sources.map((s) => s.node?.nodeName ?? 'entfernt');
console.warn(`Großer Shift (${e.value.toFixed(3)}) durch:`, nodes);
});
}).observe({ type: 'layout-shift', buffered: true });
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die Layout Instability API gibt es nur in Chromium-Browsern (Chrome, Edge, Opera). Firefox und Safari unterstützen
"layout-shift"nicht. Prüfen Sie die Unterstützung vorher mitPerformanceObserver.supportedEntryTypes.includes('layout-shift'). - Ein einzelner
value-Wert ist nicht der CLS. Sie müssen die Werte selbst zu Sitzungsfenstern zusammenfassen. Eine einfache Gesamtsumme über die ganze Lebensdauer der Seite entspricht der alten CLS-Definition und bestraft lange geöffnete Seiten. - Einträge mit
hadRecentInput === truesollten Sie herausfiltern, sonst fällt der CLS zu hoch aus. - Ohne
buffered: truefehlen Verschiebungen, die passiert sind, bevor der Observer registriert wurde. - Verschiebungen innerhalb von iframes werden nur im jeweiligen Frame gemeldet. Animationen mit
transformlösen keine Layout-Shifts aus. - Für den Produktiveinsatz empfiehlt sich die Bibliothek
web-vitals(FunktiononCLS()), die Randfälle wie bfcache und Sichtbarkeitswechsel berücksichtigt.