Use AVIF images as CSS Background

Introduction

Using AVIF images via HTML is easy as you can read in this tutorial.Furthermore, it is easy because HTML provides a media-type hint that helps the browser deliver the best version of your image. Unfortunately, CSS does not have such an option. However, with a simple Javascript function, we can easily support WebP and AVIF. We have created a detection script that manipulates the HTML element of your page by writing classes.

How CSS works

We must remember that in CSS, the first rule does not win, but the last rule wins. We have created a script that checks AVIF and WebP support by loading an AVIF-encoded 1x1 pixel image. If the browser successfully loads the AVIF image, the HTML element receives an "avif" class. If the browser does not load the AVIF image, the script will further check the browser's support for WebP using the method described above. If your browser successfully loads the image, the HTML element gets a "webp" class. Of course, this function is optional, and you can remove it according to your preferences. If it is unlikely that your browser will not pass this test, the HTML element will get a class called 'fallback'.

1<html class="fallback"></html> <!-- you have to use jpg (oh god)-->
2<html class="webp"></html> <!-- you can use webp-->
3<html class="avif"></html> <!-- you can use avif (heck yeah!)-->

AVIF support detection script

To avoid visible image changes when adding the avif/webp class to your DOM, add the following content as an inline script in your header above any CSS content. The minified version of this script is a tiny 600-byte-piece and takes 5ms to load, which is perfectly fine for the benefit it provides.

1function addClass(className) {
2 document.documentElement.classList.add(className);
3}
4var avif = new Image();
5avif.src =
6 "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
7avif.onload = function () {
8 addClass("avif");
9};
10avif.onerror = function () {
11 check_webp_feature(function (isSupported) {
12  if (isSupported) {
13   return addClass("webp");
14  }
15  return addClass("fallback");
16 });
17};
18function check_webp_feature(callback) {
19var img = new Image();
20img.onload = function () {
21var result = img.width > 0 && img.height > 0;
22callback(result);
23};
24img.onerror = function () {
25callback(false);
26};
27img.src =
28"data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
29}
30

Minified version (800 Bytes):

1function addClass(A){document.documentElement.classList.add(A)}var avif=new Image;function check_webp_feature(a){var e=new Image;e.onload=function(){var A=0<e.width&&0<e.height;a(A)},e.onerror=function(){a(!1)},e.src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=="}avif.src="data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=",avif.onload=function(){addClass("avif")},avif.onerror=function(){check_webp_feature(function(A){return addClass(A?"webp":"fallback")})};

Code Snippet

Once implemented, we can use the following CSS due to the high-level classes and cascading.

1/* Simple approach */
2.fallback .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') }
5/* Add Support for high Pixel Ratio Devices (Retina) */
6@media
7  screen and (min-resolution: 2dppx),
8  screen and (-webkit-min-device-pixel-ratio: 2),
9  screen and (min-resolution: 192dpi) {
10  .fallback img { background-image: url('avif-in-css@2x.jpg') }
11  .webp .img { background-image: url('avif-in-css@2x.webp') }
12  .avif .img { background-image: url('avif-in-css@2x.avif') }
13}

Using this script leads to the following screenshots. Chrome currently supports AVIF, so AVIF is displayed. Edge does not support AVIF and supports WebP, so our site has a webp class.

our website on chrome gets an avif classmicrosoft edge with a webp class in the html element

SCSS background mixin

Earlier this week, Raoul Kramerposted an SCSS background mixin that can be used 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 }
15}

Future implementation

The World Wide Web Consortium (W3C) is developing the CSS Images Module Level 4, which allows us to define the image type. The image-set property will enable us to specify different image formats. The browser renders the first image format supported by the browser. The following example shows how type() can deliver multiple images in high-quality and older formats that are more widely used. Note that the AVIF is shown first, as both pictures have the same resolution. JPEG, which comes second, is automatically deleted in user agents that support AVIF images. However, older user agents ignore AVIF images because they know they do not support image / avif files and instead select JPEG images.

1background-image:
2 image-set(
3  "zebra.avif" type("image/avif"),
4  "zebra.webp" type("image/webp"),
5  "zebra.png" type("image/png")
6 );

Currently, 90% of browsers support image-set but do not yet support type declaration. This is a brand-new feature for CSS4. Until browsers support this feature, we must use JavaScript to detect AVIF and WebP support.

Generating AVIF images

Creating AVIF files with avif.iois child's play. Drag the files into the converter, and it will do the rest. You will get the best results in the shortest time.

Update

Huge thanks to Stephanie Hsufor pointing out that the fallback image needs a class as well, otherwise JPG & AVIF will be downloaded. We've updated the tutorial!

We use cookies for our services.
OK