How to detect if the Webp image format is supported in the browser with JavaScript

How to detect if the Webp image format is supported in the browser with JavaScript

The WebP image format, is known for providing a superior lossless and lossy compression for images around the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web incredibly faster. WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index. For more information about this format, please be sure to read its introduction by the Google Developers here. Till the date, you can't verify wheter this format is supported in the browser in JavaScript using a predefined method, however you can create your own method to do it using a little trick.

The logic to verify if the webp format is supported with Plain JavaScript is the following: the first you need is a base64 string with some image in webp format, in this case we'll use a white image of 1px that is already in this format, then this string needs to be converted into a Blob. There are many ways to convert a base64 string to a blob, however one of the most easiest is using the fetch API that is available in the browser and then calling the blob method from it. This will be already a blob that can be interpreted by the createImageBitmap function of the browser. The createImageBitmap method exists on the global in both windows and workers. It accepts a variety of different image sources, and returns a Promise which resolves to an ImageBitmap.

In this article, we'll share with you 2 methods that will help you to verify if this format is supported on your browser with different JavaScript versions.

Standard JavaScript

Using the tipical approach with callbacks that is supported everywhere (as long as the fetch API is supported)

function WebpIsSupported(callback){
    // If the browser doesn't has the method createImageBitmap, you can't display webp format
    if(!window.createImageBitmap){
        callback(false);
        return;
    }

    // Base64 representation of a white point image
    var webpdata = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA=';

    // Retrieve the Image in Blob Format
    fetch(webpdata).then(function(response){
        return response.blob();
    }).then(function(blob){
        // If the createImageBitmap method succeeds, return true, otherwise false
        createImageBitmap(blob).then(function(){
            callback(true);
        }, function(){
            callback(false);
        });
    });
}

Then you can use the method like:

// You can run the code like !
WebpIsSupported(function(isSupported){
    if(isSupported){
        console.log("Supported");
    }else{
        console.log("Not supported");
    }
});

ES2017

With ECMAScript 2017 you can simplify all the previous code using asynchronous functions instead of callbacks:

async function WebpIsSupported() {
    // If the browser doesn't has the method createImageBitmap, you can't display webp format
    if (!self.createImageBitmap) return false;
  
    // Base64 representation of a white point image
    const webpData = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA=';
    
    // Retrieve the Image in Blob Format
    const blob = await fetch(webpData).then(r => r.blob());

    // If the createImageBitmap method succeeds, return true, otherwise false
    return createImageBitmap(blob).then(() => true, () => false);
}

And you can test if the format is supported like:

// You can run your code like
(async () => {
    if(await WebpIsSupported()) {
        console.log('Is Supported');
    } else {
        console.log("Isn't supported");
    }
})();

Redundancy? I think yes.

Although till this point we don't have a real use-case more than to optimize image loading on application, this implementation is more informative as it can provide an idea of how to check easily if the format is supported in the browser or not. The funniest thing on the initial snippet (standard JavaScript), is that if you will include the snippet on your application and this will run on older browsers, you will need as well check for support of the fetch API and an extra way to convert the base 64 string to a blob and then use that blob with the createImageBitmap method. Checking if the fetch API is supported or using a polyfill for it, will lead to another dependency, namely the support for Promises.

Happy coding !

This could interest you

Become a more social person