Detect When an Image Is Loaded in jQuery
Detecting when dynamically loaded images are completely loaded in jQuery can be tricky due to browser caching and asynchronous rendering. Standard load event listeners often fail if an image is retrieved from the browser cache before the event handler is bound. This guide explains the most reliable techniques for ensuring an image is fully loaded, covering both newly created elements and dynamically updated existing elements.
The Problem with Simple
.on('load')
Binding only a standard load handler leads to race conditions:
// Unreliable for cached images
$('#myImage').on('load', function() {
console.log('Image loaded');
}).attr('src', 'new-image.jpg');If the image is already cached, some browsers will not trigger the
load event, causing the callback to never execute.
The Most
Robust Method: Check .complete and
naturalWidth
The most reliable approach combines binding the load
event with checking the HTMLImageElement's native complete
property and naturalWidth attribute. This guarantees
execution whether the image loads from the network, returns from cache,
or fails.
function onImageReady($img, callback) {
var img = $img[0];
// If the image is already loaded and valid
if (img.complete && img.naturalWidth !== 0) {
callback.call(img);
return;
}
// Otherwise, listen for the load or error event once
$img.one('load', function() {
callback.call(this);
}).one('error', function() {
console.error('Failed to load image:', img.src);
});
}Loading Newly Created Images
When creating an <img> element entirely from
scratch in jQuery, ensure all event handlers are attached
before the src attribute is assigned:
$('<img />')
.one('load', function() {
console.log('Image is ready:', this.src);
$('#container').append(this);
})
.one('error', function() {
console.error('Image failed to load.');
})
.attr('src', 'https://example.com/photo.jpg');By defining the load listener prior to setting
src, you prevent race conditions where the image loads
synchronously from the cache before the listener is registered.
Handling Asynchronous Workflows with Promises
To integrate dynamic image loading into modern asynchronous workflows, wrap the detection logic in a Promise:
function loadImage(src) {
return new Promise(function(resolve, reject) {
$('<img>')
.one('load', function() {
resolve(this);
})
.one('error', function(err) {
reject(new Error('Image failed to load: ' + src));
})
.attr('src', src);
});
}
// Usage
loadImage('https://example.com/photo.jpg')
.then(function(img) {
$('#gallery').append(img);
})
.catch(function(err) {
console.error(err);
});This Promise-based pattern offers a clean, non-blocking interface
that works smoothly with async/await and eliminates
cached-image bugs across all modern browsers.