Hakim
Hakim

Reputation: 482

How does the browser pick the right image using <img> "sizes" and "srcset" attributes?

How does the srcset attribute determine the correct image in conjunction with the sizes attribute? Take this image for example:

<img alt="Demo image"
     sizes="(min-width: 1024px) 512px,
             100vw"
     srcset="img/banner-large.jpg 2048w,
             img/banner-medium.jpg 1400w,
             img/banner-small.jpg 800w">

(I cleared the cache in Chrome)

I thought that the last image would always be chosen (800w), because of the 512px (sizes) and the image width of 800w (srcset), but that image did not always get selected? Why?

Upvotes: 6

Views: 3015

Answers (2)

manu4543
manu4543

Reputation: 556

Here is a detailed guide on using Srcset with sizes.

sizes attribute contains a comma-separated list. Each item in the list describes the size of the image in relation to the viewport.

Using the sizes attribute with srcset provides the browser with enough information to start downloading the right image as soon as it sees an <img> tag in HTML without waiting for styles sheets to complete downloading and parsing.

Why do we need sizes?

If you are wondering why the browser is not aware of how big the image will render, checkout how the browser loads a web page.

The syntax:

<img src="image.jpg" 
     srcset="small.jpg 300w,
             medium.jpg 600w,
             large.jpg 900w"
     sizes="(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 900px"
/>

Each comma-separated item in sizes has:

  1. Media conditions, for example, (max-width: 300px) - It describes a possible state that the screen can be in. (max-width: 300px) means when the viewport width is 300 CSS pixels or less. It is similar to media queries but with some limitations. You cannot use screen or print.
  2. An empty space.
  3. The width of the image element when the media condition is true. You can provide an absolute length (px, em) or a length relative to the viewport (vw), but not percentages.

Demo - srcset with sizes

Let’s see this in action with a live demo - https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html

The layout is such that:

  • If viewport width is above 900px, each image takes a fix 225px width.
  • Upto 900px, each image takes up 33vw i.e. 33% width of total viewport width.
  • Upto 700px, each image takes up 50vw i.e. 50% width of total viewport width.
  • Upto 400px, each image takes up 100vw i.e. the whole viewport width.

HTML markup of a single image element looks like this:

<img src="https://ik.imagekit.io/ikmedia/women-dress-1.jpg" 
     srcset="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225 225w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300 300w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350 350w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640 640w"
     sizes="(max-width: 400px) 100vw, (max-width: 700px) 50vw, (max-width: 900px) 33vw, 225px">

Let’s see what happens at different screen size and DPR values -

enter image description here

Upvotes: 8

benvc
benvc

Reputation: 15120

The sizes attribute determines the media condition that applies to the current device width (the first media condition that applies is selected). Then, the browser checks the srcset attribute to find the image that most closely matches the slot size determined by the sizes attribute. Note that the browser chooses a larger image for high-res displays like Retina (usually chooses an image close to double the width it would choose on a "normal" resolution display). See Responsive images and Responsive images: If you're just changing resolutions, use srcset for a lot more detail on how this works.

So in your case, you would expect to get the banner-small.jpg image on a "normal" resolution device where device width is at least 1024px (and you would also expect to get that same image on smaller width "normal" resolution devices due to the larger widths of your other srcset image options).

Some reasons that you might not get the results you expect:

  • Older browser versions don't support srcset
  • Did not specify <meta name="viewport" content="width=device-width"> to force devices to adopt their real width when loading the page.
  • Browsers may display cached images rather than selecting the closest size match from srcset (as you noted in your question).
  • When attempting to display multiple sizes of the same image on a page, browsers may download only the largest image needed and use it in each instance (rather than downloading multiple images).
  • If you are attempting to test image selection behavior in some sort of sandboxed iframe environment like jsfiddle, it is difficult to be sure that the browser is interpreting the size of the display pane as "device width" (I have had mixed results with srcset in these types of environments). It seems to behave reasonably in a SO snippet for browsers like Chrome and Firefox (as long as you clear the cache). See below for an example snippet (better used in your own environment) that makes it visually obvious which image has been selected when testing.

<img srcset="https://via.placeholder.com/300x150 300w,
             https://via.placeholder.com/600x300 600w"
     sizes="(min-width: 1024px) 600px,
            100vw"
     src="https://via.placeholder.com/300x150"
     alt="placeholder image">

Upvotes: 1

Related Questions