Signatur
Beschreibung
Die Eigenschaft element eines LargestContentfulPaint-Eintrags verweist auf das DOM-Element, das der Browser zum Zeitpunkt des Eintrags als größten sichtbaren Inhaltsblock erkannt hat. Typische Kandidaten sind <img>-Elemente, <image> in SVG, das Posterbild eines <video>, Elemente mit CSS-Hintergrundbild (url()) und Block-Elemente mit Textknoten.
Gebraucht wird sie vor allem beim Performance-Monitoring und Debuggen der Core Web Vitals: Die Kennzahl startTime sagt nur, wann der größte Inhalt gerendert wurde, element verrät dagegen, welches Element das war. So lässt sich zum Beispiel prüfen, ob das Hero-Bild tatsächlich das LCP-Element ist und vorab geladen (fetchpriority="high", <link rel="preload">) werden sollte.
Während die Seite lädt, meldet der Browser oft mehrere Einträge nacheinander, weil immer größere Elemente erscheinen. Maßgeblich ist der letzte Eintrag vor der ersten Nutzerinteraktion (Klick, Tastendruck, Scrollen). Der Wert ist null, wenn das Element inzwischen aus dem DOM entfernt wurde oder sich in einem Shadow-Root befindet, der nicht offengelegt werden darf.
Rückgabewert
Element des größten inhaltsvollen Anstrichs, oder null, wenn das Element nicht mehr im Dokument ist bzw. nicht offengelegt werden darf.Beispiele
LCP-Element in der Konsole ausgeben
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
// Der letzte Eintrag ist der aktuelle LCP-Kandidat
const lcp = entries.at(-1);
console.log('LCP-Element:', lcp.element);
console.log('Zeitpunkt (ms):', Math.round(lcp.startTime));
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
LCP-Element beim Entwickeln optisch hervorheben
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const el = entry.element;
if (!el) continue; // Element evtl. bereits entfernt
// Vorherige Markierung entfernen und neue setzen
document.querySelectorAll('[data-lcp]').forEach((n) => {
n.removeAttribute('data-lcp');
n.style.outline = '';
});
el.dataset.lcp = 'true';
el.style.outline = '3px dashed crimson';
}
}).observe({ type: 'largest-contentful-paint', buffered: true });
LCP-Element beschreiben und an Analytics senden
const describe = (el) => {
if (!el) return '(entfernt)';
const id = el.id ? `#${el.id}` : '';
const cls = el.classList.length ? `.${[...el.classList].join('.')}` : '';
return `${el.tagName.toLowerCase()}${id}${cls}`;
};
let lastEntry;
new PerformanceObserver((list) => {
lastEntry = list.getEntries().at(-1);
}).observe({ type: 'largest-contentful-paint', buffered: true });
// Beim Verlassen der Seite den finalen Wert melden
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden' && lastEntry) {
const payload = JSON.stringify({
lcp: Math.round(lastEntry.startTime),
element: describe(lastEntry.element),
url: lastEntry.url || null,
});
navigator.sendBeacon('/analytics/lcp', payload);
}
});
// Wichtig · Fallstricke
- Keine Element-Referenz serialisieren: Ein
Elementlässt sich nicht perJSON.stringifysinnvoll übertragen. Für Analytics einen CSS-Selektor, Tag-Namen oderidableiten. nullprüfen: Wurde das Element entfernt (z. B. ein Karussell- oder Lade-Platzhalter), liefert die Eigenschaftnull. Immer vor dem Zugriff prüfen.- Mehrere Kandidaten: Frühe Einträge sind nur Zwischenstände. Erst der letzte Eintrag vor einer Nutzereingabe bzw. vor
visibilitychangeaufhiddenist der endgültige LCP. - Speicher: Wer Einträge dauerhaft aufbewahrt, hält damit auch DOM-Knoten am Leben. Nur den letzten Eintrag speichern oder die Beschreibung direkt ableiten.
- Kompatibilität: Unterstützt in Chromium-Browsern (Chrome, Edge, Opera) seit Version 77, in Firefox seit 122 und in Safari erst seit kurzem (26.2). Vorher mit
PerformanceObserver.supportedEntryTypes.includes('largest-contentful-paint')prüfen. - Zeitangaben bei Bildern von fremden Domains ohne
Timing-Allow-Origin-Header können ungenau sein.elementist trotzdem gesetzt.