How to use WebP with fallback option

How to use WebP with fallback option

WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster.

What else can I add except that we should be using this all over the internet. Similar to Service Worker and Progressive Web Apps, WebP is a hidden feature most developers don’t use or haven’t even heard of but pays off a lot. But how much ?

According to WebP you can expect about 26% size reduction for PNGs and 25-35% for JPEGs. I have used it now for some time and I just confirm those numbers and even add that it is way more sometimes. But why isn’t everyone using it ? Well similar to Service Workers, not all browsers support it which is why the following demo won’t work on every browser:

Japanese image

Japanese image


Ok the first image is the PNG which I have to say is already reduced in size and quality for efficiency. It was originally 600KB now it is 141KB. Doesn’t sound bad, so what about the WebP image ? Well I just converted the reduced PNG to WebP and it is 9.4KB large which as you can see is way more than the promised 26%. I have to say that I cheated a little here. When I converted the image I also reduced the quality which if you have a great eye you can notice it but for my use case it was ok, so I left it like that. Great so lets learn how to convert images to WebP.

Convert PNG and JPG to WebP

As usual when working with Images we need a tool and in this case is Image Magick and WebP. Installing both is fairly simple using Homebrew:

brew install imagemagick
brew install webp

Now all we need is a small script to avoid typing things over and over again. This will convert JPGs:

#!/bin/sh
# convert_jpg.sh
SRC="$1"
convert $SRC.jpg -quality 50 -define webp:lossless=true $SRC.webp

and this will convert PNGs:

#!/bin/sh
# convert_png.sh
SRC="$1"
convert $SRC.png -quality 50 -define webp:lossless=true $SRC.webp

Save your script and make it an executable using chmod

chmod +x convert_jpg.sh
chmod +x convert_png.sh

Now we can convert images like this:

./convert_jpg.sh my-image.jpg
./convert_png.sh my-image.png

I know this looks very tedious but there are toolkits like Grunt and Gulp for this. On a larger scale we want to scale this same approach and the way we will do it is using Gulp this time. For that, we have to install it and all the modules required to make it happen. First we will need a folder where we are going to work and inside we will place a new folder with our PNGs and JPGs. The folder structure should look something like this:

test_folder
└── image_source

Now we navigate into that folder and run:

npm init
npm install gulp-cli -g
npm install gulp --save-dev
npm install imagemin --save-dev
npm install imagemin-webp --save-dev
touch gulpfile.js

Great we installed the Gulp Command Line Interface as well as Gulp itself and the two modules needed to process images and convert them. Now we can get our hands dirty writing our gulpfile.js:

const gulp = require('gulp');
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');

gulp.task('default', function() {
 imagemin(['image_source/*.{jpg,png}'], 'build', {
  use: [
   imageminWebp({quality: 50})
  ]
 }).then(() => {
  console.log('Images optimized');
 });
});

So what did we do ? We create a Gulp Task that will run by default when we type gulp in our CLI. We tell Gulp to take all the images inside the image_source folder, convert them to WebP and move them to the build folder.

For this guide we will use the images I use for my portfolio site:

image_source/
├── bitcoin.png # 147KB
├── blog.png # 98KB
├── chat.png # 142KB
├── christian.png # 115KB
├── japanese.png # 145KB
└── nasa.png # 117KB

We run our gulp task and watch our results in the build folder:

build/
├── bitcoin.webp # 8KB
├── blog.webp # 4KB
├── chat.webp # 6KB
├── christian.webp # 4KB
├── japanese.webp # 7KB
└── nasa.webp # 3KB

Great so we know two things now:

  1. WebP is incredibly efficient
  2. It isn’t supported by all browsers

Fallback Option for WebP

Until all the browsers support it, we can add a simple fallback option using the HTML srcset:

<picture>
  <source srcset="/path/to/webp/bitcoin.webp" type="image/webp">
  <img src="/path/to/png/bitcoin.png" alt="bitcoin image">
</picture>

This way if the browser supports WebP, it will load the WebP image else it will load the PNG it is a win - win for everyone.