Signatur
Beschreibung
Das Interface LargestContentfulPaint gehört zur Performance-Timeline-API und beschreibt einen Eintrag vom Typ "largest-contentful-paint". Der Browser erzeugt einen solchen Eintrag, sobald ein neues, größeres Inhaltselement im sichtbaren Bereich gerendert wurde. Das können Bilder (<img>, <image> in SVG, Poster von <video>), Elemente mit CSS-Hintergrundbild oder Blockelemente mit Text sein. Maßgeblich ist der letzte gemeldete Eintrag vor der ersten Benutzereingabe. Er ergibt den Wert der Core-Web-Vital-Metrik Largest Contentful Paint (LCP).
Instanzen erstellt man nicht selbst. Man bekommt sie über einen PerformanceObserver mit type: "largest-contentful-paint". Zusätzlich zu den geerbten Eigenschaften von PerformanceEntry (entryType, startTime, duration ist immer 0, name ist immer "") gibt es folgende Eigenschaften:
element: das betroffene DOM-Element odernull, wenn es inzwischen aus dem DOM entfernt wurde.renderTime: Zeitpunkt, zu dem das Element auf dem Bildschirm dargestellt wurde, alsDOMHighResTimeStamp.loadTime: Ladezeitpunkt der Ressource. Bei Text ist der Wert0.size: sichtbare Fläche des Elements in Quadratpixeln.id: dieiddes Elements oder ein leerer String.url: die Bild-URL. Bei Text ist sie leer.toJSON(): gibt eine JSON-taugliche Darstellung des Eintrags zurück.
Die API eignet sich für Real User Monitoring (RUM): Man misst, wann Nutzer den Hauptinhalt tatsächlich sehen, und findet heraus, welches Element diesen Zeitpunkt bestimmt. Oft ist es ein Hero-Bild, dessen Laden man mit fetchpriority="high" oder Preload beschleunigen kann.
Rückgabewert
PerformanceObserver mit entryType === "largest-contentful-paint". startTime entspricht renderTime bzw. loadTime, falls renderTime nicht verfügbar ist.Beispiele
LCP mit PerformanceObserver beobachten
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:', Math.round(lcp.startTime), 'ms', lcp.element);
});
// buffered: true liefert auch Einträge, die vor dem Registrieren entstanden sind
observer.observe({ type: 'largest-contentful-paint', buffered: true });
LCP-Element und Details analysieren
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.table({
tag: entry.element?.tagName ?? '(entfernt)',
id: entry.id || '-',
url: entry.url || '(Text)',
size: entry.size,
loadTime: Math.round(entry.loadTime),
renderTime: Math.round(entry.renderTime),
startTime: Math.round(entry.startTime)
});
}
}).observe({ type: 'largest-contentful-paint', buffered: true });
Endgültigen LCP-Wert an den Server melden (RUM)
let lcpValue = 0;
let lcpElement = '';
const po = new PerformanceObserver((list) => {
const last = list.getEntries().at(-1);
lcpValue = last.startTime;
lcpElement = last.element?.tagName ?? '';
});
po.observe({ type: 'largest-contentful-paint', buffered: true });
const report = () => {
if (!lcpValue) return;
po.takeRecords(); // noch ausstehende Einträge abholen
po.disconnect();
navigator.sendBeacon('/rum', JSON.stringify({
metric: 'LCP',
value: Math.round(lcpValue),
element: lcpElement
}));
lcpValue = 0;
};
// Beim Verlassen oder Verstecken der Seite den finalen Wert senden
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') report();
}, { once: true });
Feature-Erkennung
const supportsLCP =
'PerformanceObserver' in window &&
PerformanceObserver.supportedEntryTypes?.includes('largest-contentful-paint');
console.log('LCP unterstützt:', !!supportsLCP);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Chromium (Chrome, Edge, Opera) ab Version 77, Firefox ab 122, Safari erst seit Version 26. Die API gehört nicht zu Baseline. Deshalb vorher immer über
PerformanceObserver.supportedEntryTypesprüfen. - Mehrere Einträge: Der Browser meldet jeden neuen, größeren Kandidaten. Gültig ist nur der letzte Eintrag vor der ersten Benutzereingabe. Nach Klick, Tastendruck oder Tippen kommen keine neuen Einträge mehr. Scrollen und Hover beenden die Messung nicht.
buffered: trueverwenden: Ohne diese Option fehlen Einträge, die entstanden sind, bevor der Observer registriert wurde. Mitperformance.getEntriesByType()bekommt man LCP-Einträge nicht.- Cross-Origin-Bilder: Sendet der Server keinen
Timing-Allow-Origin-Header, istrenderTimebei Bildern von fremden Domains je nach Browser0oder nur grob gerundet. Dann greiftstartTimeaufloadTimezurück. - Hintergrund-Tabs: Wurde die Seite im Hintergrund geladen, ist der LCP-Wert nicht aussagekräftig. Solche Messungen sollte man verwerfen, z. B. anhand von
document.visibilityStatebeim Laden. - Entfernte Elemente: Wird das Element aus dem DOM entfernt, ist
elementnull. Den Tag-Namen oder Selektor deshalb gleich im Callback sichern. - Für eine robuste Messung, die auch Randfälle wie bfcache und Prerendering abdeckt, empfiehlt sich die Bibliothek
web-vitals.