Responsibly delivering images

By
Grant Vinson

Images have a huge impact on a website's performance, simply due to their file size and type. Thankfully, today, we have ways to deliver the best option to users. When we stop and think about how images are loaded, what image type is the best solution, and how optimized an image is, we can keep a site's literal cost down and stay within our performance budget.

What types of images do we have?

There are multiple image types we can choose when we save out our images: JPEG, GIF, PNG-8, PNG-24, WebP, SVG and a few other less popular types we won't get into. How can we choose the best type with so many options?

  • SVG (Scalable Vector Graphics)
  • Good for sharp, vector images
  • Can be animated in browser and interactive
  • Small file size
  • Not for photographs and not supported in legacy browsers
  • GIF (Graphics Interchange Format)
  • Uses several algorithms to approximate the colors in the image, with the limited palette of 256 colors available.
  • Can be animated
  • Supports transparency
  • Dithering gives the appearance of smoother blends
  • Does not compress horizontally
  • Not the best solution for high-quality photographs due to limited colors
  • Best practice is to replace non-animated GIFs with PNG-8s
  • PNG (Portable Network Graphics)
  • PNG-8s are very similar to GIFs, except they can be optimized horizontally and vertically; however, they can't be animated
  • PNG-24s support 24-bit images and preserve transparency with smooth edges, unlike GIFs
  • Supports RBG (millions of colors), gray scale, indexed colors and bitmap image modes
  • JPEG (Joint Photographic Experts Group)
  • Best for high-quality photographs with tons of colors
  • Supports CMYK, RGB and gray scale
  • Unlike GIFs, JPEGs retain all color information in an RGB image but compress the file size by selectively discarding data
  • Does not preserve transparency
  • Quality can be adjusted which can impact file size and image weight
  • WebP
  • Supports lossless and lossy compression
  • Supports transparency and animation
  • Uses several algorithms to predict a color range value, and then encodes the difference between the prediction and the actual value
  • Only supported in Chrome, Opera and Android currently

Image delivery

Today, the picture element is being talked about quite a bit. Take a look at Sitepoint, A List Apart or just google HTML5 Picture Element, and you will access a bountiful amount of information. Still, after reading about the element, listening to speakers talk about the element and even implementing the element, a few questions and “how do Is” have come to light.

In short, the picture element can be used to deliver the correct image based on the viewport's attributes and can help with art direction. From here on, I am going to assume you have a basic knowledge of this element; if not, I suggest reading the articles linked in the above paragraph.

The Oslo /img/current/responsible-pictures/Opera House

<picture>
    <source
        media="(min-width: 1280px)"
        sizes="50vw"
        srcset="opera-fullshot-200.jpg 200w,
            opera-fullshot-400.jpg 400w,
            opera-fullshot-800.jpg 800w,
            opera-fullshot-1200.jpg 1200w">
    <img
        src="opera-closeup-400.jpg" alt="The Oslo Opera House"
        sizes="(min-width: 640px) 60vw, 100vw"
        srcset="opera-closeup-200.jpg 200w,
            opera-closeup-400.jpg 400w,
            opera-closeup-800.jpg 800w,
            opera-closeup-1200.jpg 1200w">
</picture>

In this example, the image that will be delivered is determined by the viewport's width and pixel density. If the viewport is wider than 1280px, the image will be half of the viewport's width (50vw); if it is between 640px and 1279px, the image will be 60 percent of the viewport's width; and for 639px and below, the image will be as wide as the viewport (100vw is 100 percent viewport width).

The srcset attribute with the width descriptor will load the appropriate image based on the viewport's width and pixel density. If the viewport is 200px wide or 100px wide with a 2x pixel density, the xxx-200.jpg image will be used. The same applies to the other image sizes.

The source attribute can be used to deliver different types of images based on the browser's support. For example, you can serve an image in WebP format to browsers that support it, an SVG image to browsers that don't support WebP but do support SVG, a 1x or 2x pixel density PNG that doesn't support WebP or SVG, and, finally, a JPEG image fallback for all others.

Liquidfish

<picture>
    <source type="image/webp" srcset="logo.webp">
    <source type="image/svg+xml" srcset="logo.svg">
    <source type="image/png" srcset="logo.png 1x, logo@2x.png 2x">
    <img src="logo.jpg" alt="Liquidfish">
</picture>

Inspect the examples' images to see what your browser has chosen to serve to you. Resize the browser window width to see the images swap. You can figure this out by finding the image in the network tab of Chrome's web inspector.

Conclusion

The picture element is great for delivering the most optimal image to users. If used correctly, and responsibly, this will greatly impact your site's performance and improve conversion rates. Taking a few extra minutes to save out multiple types of images will not only help performance, but it can also help with the look and feel of your site. For example, you can swap JPEGs with text in them, so the text is larger and more readable on smaller devices.

Browser support is currently limited to Chrome, Firefox, Android and IE Edge, but, thankfully, the wonderful people at Filament Group have created a pollyfill for us: picturefill.js to the rescue!

Be sure to check out the guide to images by Google for best practices on implementing this element and delivering the best images for your site.