Joe Gilmore

12 min read

How to use the HTML Picture Tag

An explanation of how you can use the HTML <picture></picture> tag on your website or blog to correctly re-size and optimize your images using WebP and AVIF formats

How to use the HTML Picture Tag

The HTML <picture> element

Not so long ago, there was either JPEG, PNG, GIF! Those were you main choices, and even I remember a graphic design friend of mine once wondering why his website was so slow when he was using pure BMP images ๐Ÿ˜…

Today, we are starting to see much wider use of better image compression algorithms for images. 2 of the main contenders are currently WEBP and AVIF

Unfortunately, just like the old VHS vs BetaMax wars of the 80's or the Blue-way vs HD DVD wars of 2000's - we do not know which of the above 2 formats will be the ultimate winner (maybe both will!) and in order to fully support older browsers (who the f*ck still uses an old browser anyhow???) we still need to make sure our older formats can still be used!

So... Introducing the <picture> tag

Lets jump straight into some code:

    <source srcSet="orange-lg.jpeg" media="(min-width: 1280px)" />
    <source srcSet="green-md.jpeg" media="(min-width: 640px)" />
    <source srcSet="red-sm.jpeg" media="(min-width: 0px)" />
    <img className="mx-auto" src="mud-lg.jpeg" alt="Demo Image" width="1280" height="800" />

And here's the result:

Demo Image

Hint: Resize your browser to see the different images loaded.

We are essentially using 4 different images here:

  • orange-lg.jpeg = 1280x800 18,316 bytes
  • green-md.jpeg = 640x400 8,897 bytes
  • red-sm.jpeg = 320x200 3,970 bytes
  • black-lg.jpeg = 1280x800 8,047 bytes (This is our catch all image for older browsers)

I'm using these coloured images as I simply want to demonstrate how when we resize our browser we get given a different image as each of the breakpoints so give it a try (if you're on a mobile device then sorry you'll just have to take my word for it!)

We are taking advantage of the <picture>'s <source> element, and if you notice our original <img> element remains intact but for any modern browser this elements src will essentially be ignored, and only our images within the matching media query <source> above it will load.

Mobile devices (most of them anyhow) will load the yellow smaller image only, and only as we increase the screen width will the larger images load. A larger screen size generally speaking means we are more likely to be dealing with a Desktop type device where speed isn't necessarily as critical, and we can happily load a bigger resolution image.

Modern Formats:

So far in the examples above we have only used JPEG images, but if we also convert them to WEBP and AVIF formats we see some significant savings:

Image NameFormatSize
orange-lg.JPEG18,316 bytes
orange-lg.WEBP10,928 bytes
orange-lg.AVIF4,739 bytes

Using these modern formats does always produce better results when optimizing images.

So what does it look like to include these? Well take a look at the following:

    <!-- AVIF: -->
    <source srcSet="orange-lg.avif" media="(min-width: 700px)" type="image/avif" />
    <source srcSet="green-md.avif" media="(min-width: 420px)" type="image/avif" />
    <source srcSet="red-sm.avif" media="(min-width: 0px)" type="image/avif" />
    <!-- WEBP: -->
    <source srcSet="orange-lg.webp" media="(min-width: 700px)" type="image/webp" />
    <source srcSet="green-md.webp" media="(min-width: 420px)" type="image/webp" />
    <source srcSet="red-sm.webp" media="(min-width: 0px)" type="image/webp" />
    <!-- JPEG: -->
    <source srcSet="orange-lg.jpeg" media="(min-width: 700px)" type="image/jpeg" />
    <source srcSet="green-md.jpeg" media="(min-width: 420px)" type="image/jpeg" />
    <source srcSet="red-sm.jpeg" media="(min-width: 0px)" type="image/jpeg" />
    <!-- Default: -->
    <img className="mx-auto" src="orange-lg.jpeg" alt="Demo Image" width="1280" height="800" />

This will mean that browsers that support AVIF formats will load them (Chrome, Opera Firefox, Edge), browsers that do not support AVIF but support WEBP will load the WEBP and then browsers that only support JPEG will load those, finally, browsers that do not even support the <picture> tag will load our default image!

Demo Image

๐Ÿ‘† Depending on your browser you'll see either AVIF, WEBP or JPEG Imqages in the example above

As you may have noticed... the HTML for this is a bit of a mouthful, so lets try and create a shorthand version of this: