How to check if the browser supports AVIF images

4.4k Views Asked by At

How can I detect if the browser supports AVIF images using JavaScript? I have viewed this question and after reading the answers I was able to build a useful one-liner function to check browser support for various image types.

const isSupported = (type) => document.createElement('canvas').toDataURL(`image/${type}`).indexOf(`data:image/${type}`) === 0;

And it works fine for webp (and jpeg & png) images. But it's not working for avif (and gif) images.

By the word Not working, I mean the function is returning false even if the browser supports AVIF images.

So, what is wrong with this approach? And what is the correct way to detect browser support for avif images using JavaScript?

3

There are 3 best solutions below

0
On BEST ANSWER

as far as I can tell, the browser can't create AVIF, JXL or GIF files with the toDataURL method out of a canvas. I currently use the following method to detect AVIF support via Javascript:

var avif = new Image();
avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
avif.onload = function () {
 /* do something * /
};

Another approach would be using a promise:

  new Promise(() => {
    const image = new Image();
    image.onerror = () => /* do something */
    image.onload = () => /* do something */
    image.src =
      "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
  }).catch(() => false);

We create a new Image with the smallest source possible and try to load it. This works reliably and tested on Firefox, Edge, IE, Chrome, Opera & Safari, including mobile support. Maybe you can create a oneliner for your intentions out of it! I'd love to see smarter and leaner approaches to check for AVIF support.

Sources:

  1. https://avif.io/blog/tutorials/css/#avifsupportdetectionscript
  2. https://github.com/leechy/imgsupport/blob/master/imgsupport.js
  3. https://github.com/justinschmitz97/avif.io/blob/master/components/Layout/Header.tsx
0
On

Here's another true Promise based solution.

const isFormatSupported = (format, dataUri) =>
  new Promise((resolve, reject) => {
    const image = new Image();

    image.src = `data:image/${format};base64,${dataUri}`;

    image.onload = () => {
      resolve(true);
    };

    image.onerror = () => {
      reject(format.toUpperCase() + "format not supported");
    };
  });

const supportsAvif = await isFormatSupported(
  "avif",
  "AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
);
0
On

Checking for AVIF support can be necessary to notify users with Edge version 115 and older as well as Safari version 15.x and older to update their browsers.

First let's see the not so reliable way,

function isAVIFSupported() { const img = new Image();   return img.decode ? true : false; }
if (!isAVIFSupported()) {
  // Display alert if AVIF is not supported or handle the situation your way
  console.warn("AVIF images are NOT supported.");
} else {
console.log("AVIF images are supported.");
}

Then let's see the hard proofing better way

const img = new Image();

img.onload = function() {
  if (img.naturalWidth > 0 || img.naturalHeight > 0) {
      // AVIF is supported
  } else {
      // AVIF is not supported
  }
};
// Test with 16px by 16px solid black avif encoded in base64
img.src = "data:image/avif;base64,AAAAHGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZgAAAOptZXRhAAAAAAAAACFoZGxyAAAAAAAAAABwaWN0AAAAAAAAAAAAAAAAAAAAAA5waXRtAAAAAAABAAAAImlsb2MAAAAAREAAAQABAAAAAAEOAAEAAAAAAAAAIgAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAAamlwcnAAAABLaXBjbwAAABNjb2xybmNseAABAA0AAIAAAAAMYXYxQ4EgAgAAAAAUaXNwZQAAAAAAAAAQAAAAEAAAABBwaXhpAAAAAAMICAgAAAAXaXBtYQAAAAAAAAABAAEEgYIDhAAAACptZGF0EgAKCDgM/9lAQ0AIMhQQAAAAFLm4wN/TRReKCcSo648oag==";