Start · Sprachen · JavaScript · Referenz · LargestContentfulPaint

LargestContentfulPaint

Schnittstelle

Liefert Zeitinformationen zum größten Bild- oder Textelement, das vor der ersten Benutzereingabe im sichtbaren Bereich gerendert wurde, also die Core-Web-Vital-Metrik LCP.

seit JavaScript Chrome/Edge 77+, Firefox 122+, Safari 26+ (nicht B Kategorie: webapi

Signatur

interface LargestContentfulPaint extends PerformanceEntry

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 oder null, wenn es inzwischen aus dem DOM entfernt wurde.
  • renderTime: Zeitpunkt, zu dem das Element auf dem Bildschirm dargestellt wurde, als DOMHighResTimeStamp.
  • loadTime: Ladezeitpunkt der Ressource. Bei Text ist der Wert 0.
  • size: sichtbare Fläche des Elements in Quadratpixeln.
  • id: die id des 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

Typ
LargestContentfulPaint
Beschreibung
Kein Konstruktor. Einträge liefert 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: 1234 ms <img class="hero" src="/img/hero.webp">

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 });
┌────────────┬──────────────────┐ │ tag │ IMG │ │ url │ https://…/hero.webp │ │ size │ 480000 │ │ renderTime │ 1234 │ └────────────┴──────────────────┘

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);
LCP unterstützt: true

// 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.supportedEntryTypes prü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: true verwenden: Ohne diese Option fehlen Einträge, die entstanden sind, bevor der Observer registriert wurde. Mit performance.getEntriesByType() bekommt man LCP-Einträge nicht.
  • Cross-Origin-Bilder: Sendet der Server keinen Timing-Allow-Origin-Header, ist renderTime bei Bildern von fremden Domains je nach Browser 0 oder nur grob gerundet. Dann greift startTime auf loadTime zurü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.visibilityState beim Laden.
  • Entfernte Elemente: Wird das Element aus dem DOM entfernt, ist element null. 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.