3
votes

I'm trying to use <img srcset /> to load images based on the size they'll appear on the page, rather than based on the size of the viewport. Perhaps examples will help:

  • On any viewport, when the image is styled with width: 100% inside a 200px-wide <div>, img-200.jpg should load.
  • On any viewport, when the image is styled with width: 100% inside a 400px-wide <div>, img-400.jpg should load.
  • ...etc.

I've done tons of Googling, but as best as I can tell, srcset is only used for changing images based on viewport size, not image size, if that makes sense. Is that correct? Or is there hope for what I'm trying to accomplish?

1
Your assumption is correct - the graphic gets chosen by screen resolution, not by container size. So this is not the right approach. Let me think.Mr Lister
How is it decided what width the divs have? Do they have different classes, is it a percentage of the window width etc?Mr Lister
@MrLister Just whatever width they happen to appear on the page. It's not so much about the container divs as it is about how big the image itself will be. I was hoping browsers would be smart enough to say, "If the image appears at 200px wide based on the layout and the container element it's in, choose the best image for that size."jessepinho
Phrased like that, it's a good question. In fact, it's a shame this doesn't exist yet!Mr Lister
I was very disappointed when looking at ‘sizes’ that image width isn’t the deciding factor. Seems like a huge oversight. When developing components rather than pages we don’t always know how our components will fit inside their parent. The sizes attribute do any for me solve any problems because that’s not how I design pages :( plus I’m still confused how retina images fit into this - I have to specify more media queries potentially for the same image size? At least with an angular component when the image is created I already know a lot more about the context to choose an image size myself.Simon_Weaver

1 Answers

3
votes

As was mentioned in the comments, this doesn't exist yet.
However, I've been thinking. If you don't mind a little trickery, there's a workaround.
We can use an iframe.

To the contents of an iframe, its width is the viewport. So then we can use the standard srcset tricks.

Let's say our img looks like this

<img src="https://placehold.it/200x100" alt=""
  srcset="https://placehold.it/200x100 200w, https://placehold.it/500x250 500w">

using the 200x100 image at smaller resolutions (200px or less) and the 500x250 one at higher resolutions.
We can then put this in a HTML file with a zero margin around it, because the iframe expects an actual HTML document.

Now to avoid having to load multiple files, we can turn this into a data URL, which will look as follows:

data:text/html;charset=utf-8,%3Cbody style='margin%3A0'%3E%3Cimg src='https%3A//placehold.it/200x100' srcset='https%3A//placehold.it/200x100 200w, https%3A//placehold.it/500x250 500w

and all that will make our original HTML page look something like this.
Note that, to show it works, I included two iframes, which are identical in themselves. Only their CSS widths differ.

iframe {width:200px; height:100px}
iframe ~ iframe {width:400px; height:200px}
<iframe src="data:text/html;charset=utf-8,%3Cbody style='margin%3A0'%3E%3Cimg src='https%3A//placehold.it/200x100' srcset='https%3A//placehold.it/200x100 200w, https%3A//placehold.it/500x250 500w' alt=''%3E" frameborder="0">?</iframe>
<br><br>
<iframe src="data:text/html;charset=utf-8,%3Cbody style='margin%3A0'%3E%3Cimg src='https%3A//placehold.it/200x100' srcset='https%3A//placehold.it/200x100 200w, https%3A//placehold.it/500x250 500w' alt=''%3E" frameborder="0">?</iframe>