Displaying broken images with the service worker

Image not found code
Using the service worker, the fetch event can tell if and when an image is not properly loaded, after which we can fetch a new placeholder image.

Initially the go to method for handling broken images was to style with css. The technique would leverage any style to the ::before or ::after pseudo-elements on the <img> element to be applied if the image did not load successfully.

Here’s a sample of how a broken image would show using CSS styling:

Image did not load! (Broken image)

I will not explain this in much further detail, as it is not a preferred method of mine. One of the greatest cons to using this technique is major browser support. This method does not work properly on Safari.

Intercepting requests for broken images

Using the service worker, the fetch event can tell if and when a request to the browser goes wrong. This can be because the response to the fetch request was bad or the user is offline.

In the below example we can check to see if the request for an image fails and we can replace with anything we like in response.

function isImage(fetchRequest) {
    return fetchRequest.method === "GET"
           && fetchRequest.destination === "image";
}
self.addEventListener('fetch', (e) => {
    e.respondWith(
        fetch(e.request)
            .then((response) => {
                if (response.ok) return response;
                
                // User is online, but response was not ok
                if (isImage(e.request)) {
                    // do something
                }
            })
            .catch((err) => {
                // User is probably offline
                if (isImage(e.request)) {
                    // do something
                }
            })
    )
});

Displaying a “broken image” image

One direct way to handle the request for images that do not load is to call up a placeholder image in its place. As an example we will show the image like below to the user for a broken image.

image not found

We can implement this by responding to the fetch request with a new request for the placeholder image, /broken-image.png

self.addEventListener('fetch', (e) => {
    e.respondWith(
        fetch(e.request)
            .then((response) => {
                if (response.ok) return response;

                // User is online, but response was not ok
                if (isImage(e.request)) {
                    // Get broken image placeholder from cache
                    return caches.match("/broken.png");
                }
            })
            .catch((err) => {
                // User is probably offline
                if (isImage(e.request)) {
                    // Get broken image placeholder from cache
                    return caches.match("/broken.png");
                }
            })
    )
});

That is it. Once you create a service-worker.js file and link it to your website, the newly created image will show in place of the default browser broken image.

Scroll to Top