Back

WebP SASS Mixin

by Superrb

Build a super-compressed image format into your structural images with this WebP SASS mixin.

Build a super-compressed image format into your structural images with this WebP SASS mixin.

You might not have heard of the WebP image format and there is probably a reason for that; it has failed to really take off within (most) mainstream browsers. So why are we even talking about it? Well, the format was developed by Google, and this means that all Chrome browsers do support the format. 

So why do we need another image format? WebP boasts really impressive image compression (around 26%) for lossless images. Importantly, it can contain an alpha chanel for transparency. This allows us to have a legitimate alternative for PNG images with the potential to save a massive amount in file size. Granted, support at the moment is not great, but the big plus is that Chrome does support the format and it looks like Safari and Firefox support might not be too far away. Modernizr allows us to detect browser support for WebP, so there is no excuse not to give it a shot. 

I decided to write a little SASS mixin for using WebP for structural and background images for a recent build. Let's take a look.

@mixin webp-background($img,
                       $color: transparent,
                       $repeat: repeat,
                       $attachment: scroll,
                       $position: center,
                       $size: auto,
                       $type: '.png') {
    background: $color url('/frontend/img/#{$img}.webp') $repeat $attachment $position / $size;
    .no-webp & {
        background-image: url('/frontend/img/#{$img}#{$type}');
    }
}

All the mixin is doing is looking for an image by it's filename and building it as a background image with the filetype of WebP. If WebP is not supported (as detected by Modernizr), we can fallback to the original filetype. The other settings allow us to build the entire background with all of it's settings complete (size, original file type, repeat etc.)

Lets look at how to use the mixin.

@include webp-background($img: 'background-img');

This is the basic usage. The only required parameter is the name of the image. Notice there is no file extension as this is applied by our mixin. Based on the settings in our mixin, this will look for /frontend/img/background-img.webp for those browsers that can and /frontend/img/background-img.png for those that can't. 

There are plenty of other settings included for you to fine tune for each use or globally with the defaults in the mixin. For example, if you wanted to use a JPG instead, you can pass that file extension through to the mixin;

@include webp-background($img: 'background-img', $type: '.jpg');

This mixin will assume that you have the WebP files converted, which you can do manually, online or build them into your Gulp/Grunt asset compiling process. Let's have a look at what your gulp task might look like.

gulp.task('images', function() {
    var sink = clone.sink();

    return gulp.src(config.img)
        // Only optimize changed images
        .pipe(plugins.changed(config.dist.img))

        // Imagemin
        .pipe(plugins.imagemin({
            optimizationLevel: 3,
            progressive: true,
            svgoPlugins: [{
                removeViewBox: false
            }]
         }))

         .pipe(sink) // clone image
         .pipe(webp()) // convert cloned image to WebP
         .pipe(sink.tap()) // restore original image

         // Set destination
         .pipe(gulp.dest(config.dist.img))

         // Show total size of images
         .pipe(plugins.size({ title: 'images' }));

});

This requires the use of gulp-webp and gulp-clone. I can run this function as part of my watch/build and it does all the converting of images for me. 

Ultimately, this means I am able to fit a progressive enhancement into my workflow seamlessly; it's an all-round win. Hopefully the snippets featured above will get you on track to doing the same.

Keep reading