Optimize Cross-browser Images with webp and the 'picture' Element

Josh Comeau
InstructorJosh Comeau
Share this video with your friends

Social Share Links

Send Tweet

"Legacy" image formats like jpg and png are often 2-3x larger than "next-gen" image formats like webp. In this video, we'll see how to convert our images using the cwebp utility, as well as how to use the <picture> HTML element to set fallbacks, for browsers that don't support the webp format.

Installation instructions:

  • For MacOS, you can use homebrew: brew install webp
  • For Windows and Linux, you'll need to download the appropriate precompiled utility from their downloads page

Josua Comeau: [00:00] The WebP image format was created by Google about a decade ago. They call it new, but this was a time when we still referred to webmasters, so it's not really that new. The remarkable thing about this format is that it's so much smaller than JPEG and PNGs.

[00:14] They very conservatively say 26 percent, but in my experience, it's really more like two, or three, or four times smaller. In fact, I have some files from my local website, where I converted all the assets. You can see that in some cases it's half the size, in other cases, it's a quarter of the size. Your results may vary.

[00:31] Ultimately, it cuts down on the file size quite a lot. They support transparency like PNGs, they support animation like GIFs.

[00:39] The downside, of course, is that not all browsers support this new format. It works in Edge, Firefox, and Chrome, but you lose Safari and Internet Explorer support.

[00:48] We'll need to make sure that we're treating this as a progressive enhancement, serving this new format to browsers that support it, while still serving PNGs and JPEGs for the other browsers.

[00:57] The first thing we need to do is to create some WebP images. I'm going to use the cwebp utility. This is produced officially by Google. I've included installation instructions in the description.

[01:07] The way that it works is you pass it a -q flag. This stands for quality. You can give it any number from 1 to 100. I found 70 usually works. The trick is not to go over 90 because then you don't get much of a savings.

[01:20] Next, you specify the input file. I happen to have a cat photo. Then, finally, you tell it where you want it to produce the new file. I'm going to put it in the same place but with a new webp extension.

[01:30] When you run this, you get a whole bunch of output. I don't really understand it. The important thing, you can check what it produces. You wind up with a file which is only 18 KB compared to a 62 KB input file. I'm going to do the same thing for a 3D portrait that I have of myself in PNG format. This thing winds up getting cut down to about 10K, down from 28.

[01:53] I also have a mini application that uses these two photos. Here, I have my cat photo with a cat, looks like a bird maybe or a mouse. I have a little avatar of myself. It's just two images put one on top of the other. I have a transparent PNG that I've just plopped over beside the cat.

[02:09] If I change the extension of one of these images to use the new WebP format, then everything still works as you would expect in Chrome. The problem is if you try to open this in Safari, the image doesn't load because Safari doesn't support this media type.

[02:22] What we need to do is we need to use the picture element. The picture element has a number of tricks up its sleeve. We're going to be using it to load different files, depending on the types supported by the browser.

[02:34] We'll start by adding a source. It takes srcset. For our purposes, we can pretend that this is the same as src. We'll make it our cat.webp image. We'll say that the type="image/webp." Next, we'll move the image we already have to be inside this picture. We'll change it back to use the JPEG format.

[02:54] If we check it in Chrome now, we'll see that it works. Indeed, if I try to save this image, you'll see that the prompt shows me a WebP image, whereas if I go back to Safari and refresh, you'll see that it now loads the original JPEG image. I can verify that by trying to save the photo.

[03:10] The way that this works is that the browser will go through the sources one at a time, checking to see if it supports the type that we've given it. If it does support it, then it takes this srcset and drops it into the spot for the image src. If the browser doesn't support any of the sources, then it falls back to use the underlying image.

[03:28] It's also important to note that we're keeping all of our properties on the image and not moving them to the picture. That's because the picture and the source are just used to help customize this image. I can repeat this process for my me.png.

[03:41] The really cool thing about the WebP format is that it also supports transparent images like PNGs. With this relatively small tweak, we can optimize our media and make sure that we're not sending unneeded bytes over the wire.