Signatur
Beschreibung
Mit decode() wird der Browser angewiesen, ein Bild vorab zu laden und zu decodieren, also in Pixeldaten umzuwandeln. Das zurückgegebene Promise wird erfüllt, wenn das Bild fertig decodiert ist. Wird es erst dann ins DOM eingefügt oder ausgetauscht, erscheint es ohne sichtbaren Aufbau, ohne Flackern und ohne dass der Haupt-Thread beim ersten Zeichnen wegen der Decodierung hängt.
Im Vergleich zum load-Event hat das zwei Vorteile: Erstens garantiert load nur, dass die Daten geladen sind, nicht dass sie auch decodiert wurden. Zweitens lässt sich decode() mit async/await verwenden und kommt ohne Callback-Verschachtelung aus.
Typische Einsatzfälle sind Bildergalerien und Karussells, das Austauschen von Platzhaltern gegen hochauflösende Bilder (LQIP), Bilder vorab laden, bevor eine Animation startet, und das Zeichnen auf ein <canvas>, sobald das Bild bereit ist.
Wenn das Bild nicht geladen oder nicht decodiert werden kann, etwa bei einer ungültigen URL, einem beschädigten Format oder einem leeren src, wird das Promise mit einer DOMException vom Typ EncodingError abgelehnt.
Rückgabewert
undefined erfüllt wird, sobald das Bild decodiert ist. Kann das Bild nicht geladen oder decodiert werden, wird es mit einer DOMException (EncodingError) abgelehnt.Beispiele
Bild ohne Flackern einfügen
const img = new Image();
img.src = '/bilder/hero.jpg';
img.alt = 'Titelbild';
try {
await img.decode();
document.querySelector('#hero').append(img);
console.log('Bild eingefügt:', img.naturalWidth, 'x', img.naturalHeight);
} catch (err) {
console.error('Bild konnte nicht decodiert werden:', err.name);
}
Platzhalter gegen hochauflösendes Bild tauschen
const swapToHighRes = async (placeholder) => {
const hiRes = new Image();
hiRes.src = placeholder.dataset.fullSrc;
hiRes.alt = placeholder.alt;
try {
await hiRes.decode();
placeholder.replaceWith(hiRes); // Austausch erst, wenn Pixel bereit sind
} catch {
console.warn('Hochauflösende Version nicht verfügbar:', hiRes.src);
}
};
document.querySelectorAll('img[data-full-src]').forEach(swapToHighRes);
Mehrere Bilder vorladen, dann Galerie starten
const urls = ['/g/1.webp', '/g/2.webp', '/g/3.webp'];
const preload = (url) => {
const img = new Image();
img.src = url;
return img.decode().then(() => img);
};
const results = await Promise.allSettled(urls.map(preload));
const images = results
.filter((r) => r.status === 'fulfilled')
.map((r) => r.value);
console.log(`${images.length} von ${urls.length} Bildern bereit`);
document.querySelector('.gallery').append(...images);
Auf ein Canvas zeichnen
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'anonymous'; // nötig, wenn das Canvas später ausgelesen werden soll
img.src = 'https://cdn.example.com/logo.png';
await img.decode();
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Wichtig · Fallstricke
- Leeres oder ungültiges
src: Ohnesrc, bei einem 404-Fehler oder einem kaputten Format wird das Promise mitEncodingErrorabgelehnt. Deshalb immertry/catchoder.catch()verwenden. - Kein dauerhafter Speicher-Cache: Browser können decodierte Pixeldaten wieder verwerfen, wenn das Bild nicht zeitnah ins DOM eingefügt wird. Deshalb nach dem Decodieren nicht unnötig lange mit dem Einfügen warten.
- Wenn sich
srcändert: Wirdsrcodersrcsetgeändert, währenddecode()noch läuft, kann das ursprüngliche Promise abgelehnt werden. Warten Sie also erst auf das Promise, bevor Sie die Quelle erneut ändern. srcset/sizes: Bei Bildern außerhalb des DOM wählt der Browser die Bildquelle unter Umständen ohne den späteren Layout-Kontext aus. Bei responsiven Bildern kann deshalb eine andere Auflösung geladen werden als erwartet.- Unterschied zum Attribut
decoding="async": Das Attribut ist nur ein Hinweis an den Browser. Mitdecode()dagegen erhalten Sie einen verlässlichen Zeitpunkt, an dem das Bild fertig ist. - Canvas und CORS: Bilder von fremden Domains ohne
crossOriginund passende CORS-Header machen das Canvas „tainted“. Danach schlagengetImageData()undtoDataURL()fehl. - Kompatibilität: Wird von allen modernen Browsern unterstützt, nicht aber vom Internet Explorer. Als Rückfalllösung dient das
load-Event:'decode' in img ? img.decode() : new Promise((res, rej) => { img.onload = res; img.onerror = rej; }).