Bram Vanroy
Bram Vanroy

Reputation: 28534

Understanding srcset and sizes in combination with HiDPI monitors

I have been into CSS for quite a while now, but srcset and sizes for the image element confuse me. Here is an example that I thought would work.

<img alt="Background image flowers"
    srcset="img/flowers-480.jpg 480w,
            img/[email protected] 480w 2x,
            img/flowers-768.jpg 768w,
            img/[email protected] 768w 2x,
            img/flowers-960.jpg 960w,
            img/[email protected] 960w 2x,
            img/flowers-1280.jpg 1280w,
            img/[email protected] 1280w 2x" 
    sizes="(max-width: 1279px) 100vw,
           (min-width: 1280) 1280px"
    src="img/flowers-960.jpg">

The idea is to have an image that's 100% of the viewport until the viewport is 1280px wide or wider, then the image will be fixed size. However, to compensate for higher DPI devices I thought it was recommended to add DPI descriptors (1.5x, 2x and so on), as suggested here and here.

What I thought the above code would do is:

However, when I put this through a validator I get the following error:

Error: Bad value for attribute srcset on element img: Width for image img/[email protected] is identical to width for image img/flowers-480.jpg

So clearly I am completely missing the point of how srcset and sizes work. What am I doing wrong?

Upvotes: 6

Views: 5043

Answers (5)

serraosays
serraosays

Reputation: 7899

As of 2022, I'd argue it's just easier to assume high DPI screens and leverage the breakpoint idea of srcset:

<img alt="Background image flowers"
  srcset="img/flowers-480.jpg 480w,
          img/flowers-768.jpg 768w,
          img/flowers-960.jpg 960w,
          img/flowers-1280.jpg 1280w,
          img/flowers-1920.jpg 1920w, 
          img/flowers-4096.jpg 4096w"
   sizes="(max-width: 1279px) 100vw,
          (min-width: 1280) 1280px"
     src="img/flowers-960.jpg">

Upvotes: 1

Ingo Steinke
Ingo Steinke

Reputation: 951

The "art direction use case", linked in @vbarinov's answer, quoted from developers.google.com, shows how to combine both width and pixel density as criteria for which image source to load and display:

<picture>
  <source media="(min-width: 800px)" srcset="head.jpg, head-2x.jpg 2x">
  <source media="(min-width: 450px)" srcset="head-small.jpg, head-small-2x.jpg 2x">
  <img src="head-fb.jpg" srcset="head-fb-2x.jpg 2x" alt="a head carved out of wood">
</picture>

In viewports that are at least 800 pixels wide, head.jpg should be displayed on a single density display, while head-2x.jpg should be displayed on a display with double or greater density.

Viewports below 800 pixels with, but at least 450 pixels wide, single-density displays should show head-small.jpg, while head-small-2x.jpg is for double density or greater.

The fallback image definition inside the <img> tag has another srcset that defines a double-density version (head-fb-2x.jpg) for viewports below 450 pixels width.

Single-density devices and browsers that don't support source sets or picture elements will fall back to display head-fb.jpg.

In a more complex scenario, we can also add alternative image formats, to take advantage of webp compression while providing jpg versions for browsers without webp support.

<picture>
  <source media="(min-width: 800px)" srcset="head.webp, head-2x.webp 2x" with="800" height="941">
  <source media="(min-width: 800px)" srcset="head.jpg, head-2x.jpg 2x" with="800" height="941">
  <source media="(min-width: 450px)" srcset="head-small.webp, head-small-2x.webp 2x" width="800" height="941">
  <source media="(min-width: 450px)" srcset="head-small.jpg, head-small-2x.jpg 2x" width="800" height="941">
  <img src="head-fb.jpg" srcset="head-fb-2x.jpg 2x" width="400" height="471" alt="a head carved out of wood">
</picture>

Here is a codepen of the complex example.

Upvotes: 8

HTownGirl17
HTownGirl17

Reputation: 403

According to MDN, "It is incorrect to mix width descriptors and pixel density descriptors in the same srcset attribute. Duplicate descriptors (for instance, two sources in the same srcset which are both described with '2x') are invalid, too."

You have 2x listed 4 times. That's invalid.

Here is an example from MDN:

Example 4: Using the srcset and sizes attributes

The src attribute is ignored in user agents that support srcset when using 'w' descriptors. When the (max-width: 600px) media condition matches, the image will be 200px wide, otherwise it will be 50vw wide (50% of the viewport width).

<img src="clock-demo-thumb-200.png" 
    alt="Clock" 
    srcset="clock-demo-thumb-200.png 200w,
    clock-demo-thumb-400.png 400w"
    sizes="(max-width: 600px) 200px, 50vw">

Upvotes: 2

vbarinov
vbarinov

Reputation: 521

For a combination of HPDI settings and responsive sizes for images you should actually use <picture> with a few <source> and a fallback <img> elements.

Details are in this article.

Upvotes: 2

Amit
Amit

Reputation: 46361

As defined on MDN for <img srcset="...">:

Each string is composed of:

a URL to an image, optionally, whitespace followed by one of:

  • a width descriptor, or a positive integer directly followed by 'w'. The width descriptor is divided by the source size given in the sizes attribute to calculate the effective pixel density.
  • a pixel density descriptor, which is a positive floating point number directly followed by 'x'.

You tried to use both, and that's illegal.

Upvotes: 4

Related Questions