Signatur
Beschreibung
Die Eigenschaft paintTime eines PerformanceElementTiming-Eintrags liefert den Zeitpunkt, an dem der Browser die Rendering-Phase (Stil, Layout) für den Frame abgeschlossen und mit dem Zeichnen (Paint) begonnen hat, in dem das beobachtete Element erstmals dargestellt wurde. Der Wert ist ein hochauflösender Zeitstempel in Millisekunden, relativ zu performance.timeOrigin.
Sie ergänzt die Eigenschaft presentationTime: paintTime markiert das Ende der Arbeit im Haupt-Thread, presentationTime den Moment, in dem die Pixel tatsächlich auf dem Bildschirm erscheinen. Die Differenz zeigt, wie viel Zeit Rasterung, Compositing und die Übergabe an die GPU beanspruchen. Beide Werte stammen aus dem gemeinsamen PaintTimingMixin, das auch PerformancePaintTiming und LargestContentfulPaint bereitstellen.
Einträge bekommst du nur für Elemente, die das HTML-Attribut elementtiming tragen (Bilder, Hintergrundbilder, Textknoten, Videoposter). Gelesen werden sie über einen PerformanceObserver mit dem Typ "element" und buffered: true, damit auch Einträge vor der Registrierung des Beobachters ankommen. Nützlich ist das beim Real-User-Monitoring, wenn du wissen willst, ob ein Hero-Bild oder eine Überschrift wegen blockierender Skripte (spätes paintTime) oder wegen langsamer Darstellung (großer Abstand zu presentationTime) spät erscheint.
Rückgabewert
performance.timeOrigin, zu dem die Paint-Phase des Frames begann, in dem das Element erstmals gezeichnet wurde. Bei Bildern aus anderen Ursprüngen ohne Timing-Allow-Origin-Header kann der Wert grob gerundet oder 0 sein.Beispiele
paintTime eines Hero-Bildes erfassen
// HTML: <img src="hero.jpg" elementtiming="hero-bild">
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`${entry.identifier}: paintTime = ${entry.paintTime.toFixed(1)} ms`);
}
});
observer.observe({ type: "element", buffered: true });
Paint- und Darstellungsverzögerung vergleichen
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const { identifier, loadTime, paintTime, presentationTime } = entry;
// Zeit zwischen Laden der Ressource und Paint-Beginn (Haupt-Thread blockiert?)
const renderDelay = loadTime ? paintTime - loadTime : 0;
// Zeit zwischen Paint-Beginn und Anzeige auf dem Bildschirm
const presentDelay = presentationTime ? presentationTime - paintTime : null;
console.table({ identifier, renderDelay, presentDelay });
}
});
observer.observe({ type: "element", buffered: true });
Feature-Erkennung mit Rückfall auf renderTime
const getPaintStart = (entry) =>
"paintTime" in entry ? entry.paintTime : entry.renderTime || entry.loadTime;
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const zeit = Math.round(getPaintStart(entry));
// An eigenen Analytics-Endpunkt senden
navigator.sendBeacon("/rum", JSON.stringify({ id: entry.identifier, zeit }));
}
});
if (PerformanceObserver.supportedEntryTypes.includes("element")) {
observer.observe({ type: "element", buffered: true });
} else {
console.log("Element Timing wird nicht unterstützt.");
}
// Wichtig · Fallstricke
- Kompatibilität:
paintTimeist experimentell und derzeit nur in neueren Chromium-Versionen verfügbar. Prüfe mit"paintTime" in entryund falle aufrenderTimezurück. Der Eintragstyp"element"fehlt in Safari und älteren Firefox-Versionen ganz, deshalb vorherPerformanceObserver.supportedEntryTypesabfragen. - Nur markierte Elemente: Ohne das Attribut
elementtimingentsteht kein Eintrag. Das Attribut muss gesetzt sein, bevor das Element gezeichnet wird. - Ressourcen aus anderen Ursprüngen: Liefert der Server keinen
Timing-Allow-Origin-Header, werden die Zeitwerte aus Sicherheitsgründen (Schutz vor Timing-Angriffen) gerundet oder auf0gesetzt. - Nicht gleich der Sichtbarkeit:
paintTimeliegt immer vor oder aufpresentationTime. Wann Nutzer das Element tatsächlich sehen, beschreibtpresentationTimebzw.renderTime. - Ohne
buffered: truegehen Einträge verloren, die vor dem Registrieren des Beobachters entstanden sind.