Understanding gatsby-image (Part 2): Responsive images 101

Alexa Steinbrück
3 min readDec 7, 2019

This is Part 2 of a three-part series covering the Gatsby plugin gatsby-image
Part 1:
Graphql, generated files & generated markup
Part 2: Responsive images 101
Part 3: Controlling src-set, breakpoints and styling

In this post we’ll cover these things:

  • <picture> with <source> as child elements
  • <img> with “srcset” and “sizes” attribute
  • Using the browser devtools to find out which image files are really fetched by the browser

This is providing some helpful background knowledge to use gatsby-image, but it is not specific to gatsby-image.

How does the <picture> element work?

The <picture> element contains zero or more <source> elements and one <img> element.

From MDN:

“The browser will consider each child <source> element and choose the best match among them; if no matches are found or the browser doesn’t support the <picture> element, the URL of the <img> element’s src attribute is selected. The selected image is then presented in the space occupied by the <img> element.”

“The <img> element serves two purposes: it describes the size and other attributes of the image and its presentation, and it provides a fallback in case none of the offered <source> elements are able to provide a usable image.”

How does <img> with the srcset and sizes attribute work?

Checkout the following image markup. The srcset and sizes properties use a distinct notation.

"my-img-280w.jpg 280w,
my-img-440w.jpg 440w,
my-img-800w.jpg 800w"
"(max-width: 320px) 280px,
(max-width: 480px) 440px,

srcset defines the set of images we will allow the browser to choose between, and what size each image is.” (MDN)

It reads as a string with comma-separated pairs of information: The file path followed by the width of the actual image as a number (without px) but with ‘w’ at the end.

What about the sizes attribute?

“sizes defines a set of media conditions (e.g. screen widths) and indicates what image size would be best to choose” (MDN)

It reads as a string with comma-separated pairs of information: a media condition in brackets, followed by the width of the slot the image will fill when the media condition is true.

“The last slot width has no media condition (this is the default that is chosen when none of the media conditions are true). The browser ignores everything after the first matching condition, so be careful how you order the media conditions.” (MDN)

Another option: <img> with srcset but without sizes

Check out this srcset attribute:

"my-img-300w.jpg 1x,
my-img-450w.jpg 1.5x,
my-img-600w.jpg 3x"

Instead of providing a width, we’re providing a so called x-descriptor that informs the browser to check the device pixel ratio (DPR) of the client’s monitor, and choose the right image.

This is useful for optimization for retina displays.

When should I use <picture> and when <img> & sourceset?

On first sight both ways seem to provide a solution for the same problem: Offering a choice of image files to let the browser choose from. The main guideline is:

Use <picture> for art direction and <img> & sourceset for resolution-switching.

If you’re wondering: Art direction…? But I’m not an art director! You should read this definition of art direction within the domain of web development:

Art direction: The problem whereby you want to serve cropped images for different layouts — for example a landscape image showing a full scene for a desktop layout, and a portrait image showing the main subject zoomed in for a mobile layout. (MDN)

You can solve this problem using the <picture> element.

Testing: How to check which images are REALLY requested by the browser?

⚠️ Attention: It is not what you see inside the src of the <img > tag (but it can be)! Even more confusing: It doesn’t even have to be one from the srcSet array of the img tag (but it can be)!

Two options to find out:

  • Open your browser’s developer tools “Network” Panel and checkout which file was fetched over the network
  • Open your browser’s developer tools “Inspector” or “Elements” panel: Select the img element and type into the Browser console: $0.currentSrc ($0 stands for the currently selected element)

👉 Continue with Part 3 of this series about gatsby-image: “Controlling sizes, breakpoints and styling”

Alexa Steinbrück

A mix of Frontend Development, Machine Learning, Musings about Creative AI and more