Fully support AVIF in your CSS today.

01.10.20 · 8 min read
Serving AVIF images through HTML is very easy, as you can read . Furthermore, it is straightforward because HTML offers a media-type hint, which helps the browser deliver the best version of your image. Unfortunately, CSS does not have an option like this. However, with a simple Javascript function, we can easily support WebP and AVIF. We have created a detection script that manipulates your page's HTML element by writing classes.

How it works

We have to remember that in CSS, the first rule doesn't win. It's the last rule that wins. We created a script that checks for AVIF and WebP support by loading an AVIF-encoded 1x1 pixel image. If the browser loads the AVIF image successfully, the <html> element will get an 'avif' class. If the browser fails to load the AVIF image, the script will further check the browser's support for WebP with the same method described above. If your browser successfully loads the image, the <html> gets a 'webp' class. Of course, this feature is optionally and you can remove it based on your preferences. If very unlikely, your browser also fails this test, the HTML element gets no class at all.
1<html> <!--no class at all, which means you have to use jpg (oh god)-->
2<html class="webp"> <!--which means you can use webp-->
3<html class="avif"> <!--which means you can use avif (heck yeah!)-->

The Script

To avoid visible image switching when the avif/webp class is added to your DOM, add the contents as an inline script in your <head> above any CSS content. The minified version of this script is a tiny 600 bytes piece and takes 5ms to load, which is completely fine for the benefit it provides.
1function AddClass(class) { document.documentElement.classList.add(class) };
3var avif = new Image();
6avif.onload = function () { AddClass("avif") };
8avif.onerror = function () {
9  var webp = new Image();
10  webp.src = "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
11  webp.onload = function () { AddClass("webp") }
Minified version (600 Bytes):
1function F(a){document.documentElement.classList.add(a)}var A=new Image;A.src="data:image/avif;base64,AAAAFGZ0eXBhdmlmAAAAAG1pZjEAAACgbWV0YQAAAAAAAAAOcGl0bQAAAAAAAQAAAB5pbG9jAAAAAEQAAAEAAQAAAAEAAAC8AAAAGwAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAARWlwcnAAAAAoaXBjbwAAABRpc3BlAAAAAAAAAAQAAAAEAAAADGF2MUOBAAAAAAAAFWlwbWEAAAAAAAAAAQABAgECAAAAI21kYXQSAAoIP8R8hAQ0BUAyDWeeUy0JG+QAACANEkA=",A.onload=function(){F("avif")},A.onerror=function(){var a=new Image;a.src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",a.onload=function(){F("webp")}};
Minified version without WebP detection (400 Bytes):


Once implemented, we can simply use the following CSS due to the high level classes.
1/* Simple approach */
2.img { background-image: url('avif-in-css.jpg') }
3.webp .img { background-image: url('avif-in-css.webp') }
4.avif .img { background-image: url('avif-in-css.avif') }
7/* Add Support for high Pixel Ratio Devices (Retina) */
9    screen and (min-resolution: 2dppx),
10    screen and (-webkit-min-device-pixel-ratio: 2),
11    screen and (min-resolution: 192dpi) {
12    .img { background-image: url('avif-in-css@2x.jpg') }
13    .webp .img { background-image: url('avif-in-css@2x.webp') }
14    .avif .img { background-image: url('avif-in-css@2x.avif') }

The outcome (05.01.21)

Using this script leads to the following screenshots. Back in the day, Firefox Quantum didn't support WebP or AVIF, so there is no class. Chrome currently supports AVIF, so AVIF is displayed. Edge does not support AVIF and supports WebP, so our site has a webp class.firefox quantum without any classour website on chrome gets an avif classmicrosoft edge with a webp class in the html element

SCSS background mixin

posted a f*king amazing SCSS background mixin that you can use as well to support AVIF and WebP.
1@mixin bg-url($url, $url2x: false, $webp1x: false, $webp2x: false, $avif1x: false, $avif2x: false) {
2  background-image: url($url);
3  @if $webp1x { .webp & { background-image: url($webp1x) }}
4  @if $avif1x { .avif & { background-image: url($avif1x) }}
5  @if $url2x {
6    @media
7    screen and (-webkit-min-device-pixel-ratio: 2),
8    screen and (min-resolution: 192dpi),
9    screen and (min-resolution: 2dppx) {
10      background-image: url($url2x);
11      @if $webp2x {.webp & {background-image: url($webp2x)}}
12      @if $avif2x {.avif & {background-image: url($avif2x)}}
13    }
14  }

Look into the future

The World Wide Web Consortium (W3C) is developing CSS Images Module Level 4 that will enable us to define the image type. The image-set property allows us to specify different image formats. The browser renders the first image format that is supported by the browser. The example below shows how type() can be used to serve multiple images in high-quality formats and older formats that are more widely supported. Note that the AVIF is shown first, since both images have the same resolution. The JPEG image coming second is automatically dropped in UAs which support AVIF images. However, older UAs ignore AVIF images (because it knows it doesn't support "image/avif" files), and JPEG images will be selected instead.
2	image-set(
3		"zebra.avif" type("image/avif"),
4		"zebra.webp" type("image/webp"),
5		"zebra.png" type("image/png")
6	);
Image-set is currently supported by 90% of browsers but does not support the type declaration yet. This is a brand new feature for CSS4. Until browsers support this feature, we have to use JavaScript to detect AVIF and WebP support.

Generating AVIF images

Creating AVIF files with is a nobrainer. Simply drag the files into the converter and it'll do the rest. You'll get the best results with the least time.

One last hacky way by Marble_Wraith

The reddit user marble_wraith found a hacky way to check for AVIF support. He states that the content-visibility CSS property launched in the same version of Chrome (85) and Opera (71) in which AVIF support has been added. So instead of detecting AVIF support directly, this solution checks for the browser version. However, as soon as other browsers like Safari add AVIF support, this method may stop working. We wouldn't recommend this for a production website, but it's something you can experiment with.
1@supports (content-visibility:auto) {
2    .img {background-image: url("image.avif")}

Further optimization

There are several more ways to optimize your images. Take a look at the referenced articles below.

Related topics, websites and sources

Related Questions, tags and headlines

(image format)
(avif format)
(original image)
(user experience)
(css background)
(background images)
(file size)
(file format)
(What is AVIF image format)
(Is AVIF lossless)
(Which image format can be displayed by all Web browsers)
(How do I use an AVIF file)
(Which image format is highest quality)
(Progressively delivering new image formats with CSS)
(PostCSS plugin to use AVIF in CSS background)
(avif and webp images as css background images)
(Delivering New Image Formats)
(css background-image usage of avif and webp)

Related articles

How to get started with AVIF using HTML
Enjoy this in-depth guide on how to use AVIF in HTML. Featuring examples with modern delivery standards.
Use AVIF in Frameworks like Vue, React & Angular
Serving AVIF images via JavaScript frameworks is quite easy - find out more here.
Does Windows support AVIF already?
Learn how to make AVIF images load on native Windows 10 applications such as Paint and File Explorer.
Profit from a faster website, higher ranking and better conversions.
Convert your images to AVIF for free.