How to Wait for All Images to Load in jQuery

Executing jQuery functions before images finish downloading often causes incorrect dimension calculations, broken animations, or unexpected layout shifts. While the standard $(document).ready() executes as soon as the HTML structure is parsed, it does not wait for external assets like images to render. This guide explains how to properly delay jQuery execution until all images are fully loaded across the entire page or within specific containers.

Method 1: The Native Window Load Event

The simplest and most common method to wait for all page assets—including stylesheets, scripts, and images—to load is using jQuery's $(window).on('load', ...).

Unlike $(document).ready(), the load event on the window object fires only after every resource has completely downloaded.

$(window).on('load', function() {
    // All images and resources are fully loaded
    console.log('All images are loaded.');
    
    // Run your layout or dimension-dependent code here
    var imageHeight = $('#my-image').height();
});

Method 2: Handling Specific Images with Promises

If you only need to wait for a specific set of images—such as an image gallery—waiting for the entire page to finish loading can create an unnecessary delay for users. You can use JavaScript Promise.all() alongside jQuery to monitor a specific group of images.

function waitForImages($container) {
    var promises = [];

    $container.find('img').each(function() {
        var img = this;

        if (!img.complete) {
            var promise = new Promise(function(resolve) {
                $(img).one('load error', function() {
                    resolve();
                });
            });
            promises.push(promise);
        }
    });

    return Promise.all(promises);
}

// Usage
$(document).ready(function() {
    waitForImages($('#gallery')).then(function() {
        console.log('All gallery images are loaded.');
        // Initialize carousel, masonry, or other scripts here
    });
});

Checking img.complete is essential. If an image is already cached by the browser, the load event might not fire at all, causing code that relies strictly on event listeners to hang indefinitely.

Method 3: Using the imagesLoaded Library

For complex layouts like Masonry grids or infinite scrolling, handling cached images, CSS background images, and dynamically injected content natively can be tricky. The lightweight third-party library imagesLoaded is the standard solution in the jQuery ecosystem.

Once the library is included on your page, you can bind it directly to any jQuery selector:

$('#container').imagesLoaded()
    .always(function(instance) {
        console.log('All images are loaded or failed to load.');
    })
    .done(function(instance) {
        console.log('All images successfully loaded.');
        // Execute dependent code here
    })
    .fail(function() {
        console.log('At least one image failed to load.');
    })
    .progress(function(instance, image) {
        var result = image.isLoaded ? 'loaded' : 'broken';
        console.log('Image is ' + result + ' for ' + image.img.src);
    });

Summary

  • Use $(window).on('load', ...) if your code depends on every image on the entire page and you do not want to use external libraries.
  • Use Promise.all() with img.complete verification if you only need to wait for images within a specific section of the page.
  • Use the imagesLoaded library when dealing with dynamic content, cached assets, or complex UI components like isotope and masonry layouts.