WebP image and background usage in web projects

WebP image and background usage in web projects
UPDATE: I was late at the image-set party, please read this blog post, how to support avif and webp images in your project.

With Firefox 65 joining the WebP party and thanks to the incredible squoosh app, WebP becomes more than just a lighthouse proposal. So it is time to figure out how to use WebP in every web project.

September 01, 2020: I updated the webp detection script to support avif images too. Read the new blog post about the changes.

Using WebP for <img>s in your project is possible by using the <picture> element, explained here which looks like this:

<picture>
    <source type="image/webp" srcset="image1x.webp 1x, image2x.webp 2x">
    <source type="image/jpeg" srcset="image1x.jpg 1x, image2x.jpg 2x">
    <img src="image1x.jpg" alt="describe image content">
</picture>

IE11 does not support picture element magic, so no double resolution images are displayed, but the fallback image.

But that is only half the picture ;-)

WebP progressive enhancement script

To use WebP images as background images, you must check if your browser is capable of WebP images. You can include a modernizr bundle, or search the web and find this feature detection script: https://github.com/vitaliy-bobrov/webp-support, which nearly does what I want.

So I forked this script and changed the way it is working: webp-inline-support. My idea is, to include this script as early as possible in the <head>, even before your css.

This way, the browser will directly render the page with or without the html.webp class. In addition my version uses sessionStorage, to check only one time in a visit for WebP support. Because browser support is growing, I do not use localStorage. For example: A Firefox user today (27.01.2019) will not see WebP images, but in two days, the same Firefox user is able to see WebP images.

WebP detection script usage

A <head> will look like this, with my script:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    ...
    <title>...</title>
    <script>!function(e){"use strict";function s(s){if(s){var t=e.documentElement;t.classList?t.classList.add("webp"):t.className+=" webp",window.sessionStorage.setItem("webpSupport",!0)}}!function(e){if(window.sessionStorage&&window.sessionStorage.getItem("webpSupport"))s(!0);else{var t=new Image;t.onload=t.onerror=function(){e(2===t.height)},t.src="data:image/webp;base64,UklGRi4AAABXRUJQVlA4TCEAAAAvAUAAEB8wAiMwAgSSNtse/cXjxyCCmrYNWPwmHRH9jwMA"}}(s)}(document);
    </script>
    <style>/* inline css */</style>
    ...
</head>
<body>...

SCSS mixin for WebP background images

I use SCSS and created this mixin to support WebP images (gist):

@mixin bg-url($url, $url2x: false, $webp1x: false, $webp2x: false) {
  background-image: url($url);
  @if $webp1x {
    .webp & {
      background-image: url($webp1x);
    }
  }
  @if $url2x {
    @media
    screen and (-webkit-min-device-pixel-ratio: 2),
    screen and (min-resolution: 192dpi),
    screen and (min-resolution: 2dppx) {
      background-image: url($url2x);
      @if $webp2x {
        .webp & {
          background-image: url($webp2x);
        }
      }
    }
  }
}

Hint: The .webp class increases your css specificity, so remember when you change a background-image or remove it within a @media-query a simple background-image: none; will still show your WebP image.

Generating WebP images

If you handle your images manual use Squoosh. I try to automate WebP generation within a gulp and a webpack environment, but my results are still not in production, because sometimes the WebP  image is bigger, than its jpeg/png equivalent, or I reduce the quality that much, that it does not look any good.

tbc...

Article Image from Jon Tyson via unsplash and ghost.