Signatur
Beschreibung
Die schreibgeschützte Eigenschaft naturalHeight eines PerformanceElementTiming-Eintrags gibt die intrinsische Höhe des Bildes in CSS-Pixeln an, also die Höhe der Bildressource selbst. Wie das Bild per CSS oder HTML-Attribut skaliert dargestellt wird, spielt dafür keine Rolle. Der Wert entspricht damit HTMLImageElement.naturalHeight, steht aber direkt im Performance-Eintrag zur Verfügung. Du musst also nicht mehr auf das DOM-Element zugreifen.
Die Eigenschaft gehört zur Element Timing API. Einträge entstehen nur für Elemente mit dem Attribut elementtiming, zum Beispiel <img elementtiming="hero" src="…">. Die Einträge liest du mit einem PerformanceObserver vom Typ "element" aus.
In der Praxis vergleichst du naturalHeight und naturalWidth mit der tatsächlich gerenderten Größe aus intersectionRect. So findest du überdimensionierte Bilder, die mehr Bytes laden als nötig, und kannst sie zusammen mit renderTime und loadTime an ein Monitoring-System melden.
Bei Textknoten (Einträge mit name === "text-paint") ist der Wert immer 0. Die Eigenschaft ist nur sinnvoll für <img>, für <image> in SVG und für Elemente mit CSS-Hintergrundbild (background-image).
Rückgabewert
unsigned long) mit der intrinsischen Bildhöhe in Pixeln. Bei Textelementen 0.Beispiele
Intrinsische Höhe eines Hero-Bildes auslesen
// HTML: <img src="hero.jpg" elementtiming="hero-bild" width="600">
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.identifier === 'hero-bild') {
console.log(`Intrinsische Größe: ${entry.naturalWidth}×${entry.naturalHeight}`);
}
}
});
// buffered: true liefert auch Einträge, die vor der Registrierung entstanden sind
observer.observe({ type: 'element', buffered: true });
Überdimensionierte Bilder erkennen
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Textelemente haben naturalHeight 0 – überspringen
if (entry.naturalHeight === 0) continue;
const gerenderteHoehe = entry.intersectionRect.height;
if (gerenderteHoehe === 0) continue;
const faktor = entry.naturalHeight / (gerenderteHoehe * devicePixelRatio);
if (faktor > 1.5) {
console.warn(
`"${entry.identifier}" ist ${faktor.toFixed(1)}× zu hoch ` +
`(${entry.naturalHeight}px geladen, ${Math.round(gerenderteHoehe)}px sichtbar)`
);
}
}
});
observer.observe({ type: 'element', buffered: true });
Bild- und Texteinträge unterscheiden und melden
const berichte = [];
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
berichte.push({
id: entry.identifier,
art: entry.name === 'text-paint' ? 'text' : 'bild',
hoehe: entry.naturalHeight, // bei Text immer 0
breite: entry.naturalWidth,
renderTime: Math.round(entry.renderTime || entry.loadTime)
});
}
});
observer.observe({ type: 'element', buffered: true });
// Beim Verlassen der Seite an den Server schicken
addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden' && berichte.length) {
navigator.sendBeacon('/rum', JSON.stringify(berichte));
}
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Die Element Timing API ist experimentell und nur in Chromium-Browsern verfügbar (Chrome, Edge, Opera). Prüfe die Unterstützung vorher mit
PerformanceObserver.supportedEntryTypes.includes('element'). - Ohne das Attribut
elementtimingam Element entsteht kein Eintrag.naturalHeightgibt es dann gar nicht erst. - Bei Textelementen ist der Wert immer
0. Filtere solche Einträge vor Berechnungen heraus, sonst teilst du durch null oder bekommst verzerrte Statistiken. - Der Wert beschreibt die Bildressource, nicht die Darstellung. Die sichtbare Größe liefert
intersectionRect. Bei hochauflösenden Displays solltest dudevicePixelRatioeinrechnen. - Bei Bildern aus anderen Quellen ohne
Timing-Allow-Origin-Header istrenderTime0.naturalHeightbleibt aber verfügbar. - Der Wert ist schreibgeschützt. Zuweisungen werden stillschweigend ignoriert.