What is the purpose of the sizes attribute?

In reading articles and discussing Responsive Images it's become clear to me the biggest sticking point people have with the new markup is understanding the purpose of the sizes attribute.

This demo aims to explain why sizes exists in a simple example.

Below are two images marked up with the standard RICG Responsive Images markup. The only difference between them is that the first image has its sizes attribute set to 100vw while the second image has its sizes attribute set to (min-width: 48em) 800px, 100vw.

Resizing your browser (ideally Firefox - Once a larger picture is loded Chrome will use it even on smaller viewports) or using mobile view in developer tools you will see that the image files get swapped out. The indicator is the flag in the top-left corner that displays the physical size of the different image files (the numbers are part of the image file).

Here's how the sizes attribute comes in:

In the first example the image file will switch from medium to large to extra large at the 600px, 800px, and 1200px breakpoints.

In the second example the image file will switch from small to medium and stay there unless you have a 2x or 3x resolution display.

So why is this happening?

In the first example the browser only knows the size of the viewport and the size of each of the image files through their w attributes. Because the sizes attribute is set to the default 100vw (100% of the viewport width), as the viewport increases in width, the browser keeps swapping out the image files for the one that is equal to or larger than the entire viewport, going through the entire list from small to extra large.

In the second example the sizes attribute is set to (min-width: 48em) 800px, 100vw telling the browser that if the viewport is wider than 48ems the width of the area the image will occupy is 800px. Only when the viewport is smaller than 48ems will the image take up 100% of the viewport width. As a result the image file is swapped from small to medium at 48ems and then stops being swapped out, all thanks to the sizes attribute.

In short, the sizes attribute ensures that responsive images are loaded based on the actual width they will occupy, not the total width of the viewport.

For a more in-depth (and a bit hard to parse) explanation, check out Eric Portis' srcset & sizes.