Signatur
Beschreibung
PerformanceElementTiming gehört zur Element Timing API. Damit misst du, wann ausgewählte, für den Nutzer wichtige Elemente tatsächlich auf dem Bildschirm erscheinen, zum Beispiel ein Hero-Bild, eine Überschrift oder ein Produktfoto. Anders als Largest Contentful Paint (LCP), bei dem der Browser das größte Element selbst auswählt, legst du hier fest, welche Elemente gemessen werden: Du setzt das Attribut elementtiming="bezeichner" direkt im Markup.
Einträge dieses Typs haben den entryType "element". Du liest sie über einen PerformanceObserver aus. Einen öffentlichen Konstruktor gibt es nicht, die Objekte erzeugt der Browser selbst. Beobachtet werden <img>-Elemente, <image> innerhalb von SVG, Poster-Bilder von <video>, Elemente mit CSS-background-image sowie Elemente, die Textknoten enthalten.
Wichtige Eigenschaften (alle schreibgeschützt):
renderTime: Zeitpunkt des Renderns in Millisekunden relativ zuperformance.timeOrigin. Bei ursprungsübergreifenden Bildern ohneTiming-Allow-Origin-Header ist der Wert0.loadTime: Zeitpunkt, zu dem die Bildressource geladen war. Bei Text ist der Wert0.identifier: Wert des Attributselementtiming.element: Referenz auf das DOM-Element odernull, wenn das Element nicht mehr im Dokument ist.id: dieiddes Elements.intersectionRect: sichtbares Rechteck des Elements im Viewport alsDOMRectReadOnly.naturalWidth/naturalHeight: Eigenmaße des Bildes, bei Text0.url: Anfangs-URL der Bildanfrage, bei Text ein leerer String.- Geerbt von
PerformanceEntry:name("image-paint"oder"text-paint"),entryType("element"),startTime(gleichrenderTime, ersatzweiseloadTime) undduration(immer0).
Die Methode toJSON() gibt eine JSON-Darstellung des Eintrags zurück. Das ist praktisch, wenn du Messwerte an einen Analytics-Endpunkt senden willst.
Rückgabewert
PerformanceObserver mit type: "element", in list.getEntries().Beispiele
Hero-Bild markieren und Renderzeit beobachten
// HTML: <img src="hero.jpg" elementtiming="hero-image" alt="Titelbild">
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`${entry.identifier}: gerendert nach ${Math.round(entry.renderTime)} ms`);
console.log('Geladen nach:', Math.round(entry.loadTime), 'ms');
console.log('Größe:', entry.naturalWidth, 'x', entry.naturalHeight);
}
});
// buffered: true liefert auch Einträge, die vor dem Registrieren entstanden sind
observer.observe({ type: 'element', buffered: true });
Text-Rendering einer Überschrift messen
// HTML: <h1 elementtiming="main-heading">Willkommen im Shop</h1>
new PerformanceObserver((list) => {
list.getEntries()
.filter((entry) => entry.name === 'text-paint')
.forEach((entry) => {
console.log(entry.identifier, entry.element?.tagName, Math.round(entry.startTime));
});
}).observe({ type: 'element', buffered: true });
Messwerte an Analytics senden (mit Feature-Erkennung)
const supportsElementTiming =
'PerformanceObserver' in window &&
PerformanceObserver.supportedEntryTypes?.includes('element');
if (supportsElementTiming) {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// renderTime ist 0 bei Cross-Origin-Bildern ohne Timing-Allow-Origin
const time = entry.renderTime || entry.loadTime;
const payload = JSON.stringify({
id: entry.identifier,
type: entry.name,
time: Math.round(time),
url: entry.url
});
navigator.sendBeacon('/analytics/element-timing', payload);
}
});
observer.observe({ type: 'element', buffered: true });
} else {
console.log('Element Timing wird nicht unterstützt');
}
// Wichtig · Fallstricke
- Browser-Kompatibilität: Nur Chromium-Browser (Chrome, Edge, Opera ab Version 77) unterstützen die API. Firefox und Safari kennen sie nicht. Prüfe die Unterstützung immer mit
PerformanceObserver.supportedEntryTypes.includes('element'). - Cross-Origin-Bilder: Kommt ein Bild von einem anderen Ursprung und sendet der Server keinen passenden
Timing-Allow-Origin-Header, istrenderTimeaus Sicherheitsgründen0. In diesem Fall musst du aufloadTimezurückgreifen. - Nur der erste Paint zählt: Pro Element entsteht nur ein Eintrag, nämlich für das erste Rendern. Elemente, die später eingefügt oder ausgetauscht werden (etwa ein neues
src), erzeugen nicht zuverlässig neue Einträge. - Das Attribut muss früh vorhanden sein: Setzt du
elementtimingerst nachträglich per JavaScript, nachdem das Element schon gerendert wurde, wird es nicht mehr erfasst. - Ohne
buffered: trueverpasst der Observer Einträge, die entstanden sind, bevor dein Skript lief.performance.getEntriesByType('element')liefert solche Einträge nicht. elementkannnullsein, wenn das Element inzwischen aus dem DOM entfernt wurde. Verwende deshalb optionales Verketten (?.).- Die API ist experimentell. Die Spezifikation liegt bei der WICG und ist kein W3C-Standard.