0
votes

I want my responsive Webpage to load the appropriately sized images. I currently have an HTML template that looks like:

  <picture>
  <source media="(min-width: 950px)" srcset="{{ .Cover.Large }}">
  <source media="(min-width: 600px)" srcset="{{ .Cover.Medium }}">
  <source media="(min-width: 300px)" srcset="{{ .Cover.Small }}">
  <source media="(min-width: 150px)" srcset="{{ .Cover.Xsmall }}">
<img src="{{ .Cover.Medium }}" alt="{{ .Title }} poster">
  </picture>

Large = 950x400 Medium = 600x252 Small = 300x126 Xmall = 150x63

Now I'm thinking this min-width is not going to work very well if the pictures are in a row or flexed. Isn't it best to define the dimensions of the image and let the browser download the most suitable source?

https://html.spec.whatwg.org/multipage/embedded-content.html#valid-source-size-list

What's the cleanest way to do this? Confusingly in my own responsive experiments, the Large size is always loaded:

Large image always loaded

2

2 Answers

0
votes

First of all, are you using the same image for each scenario but only in different sizes? If so, you can probably just use the srcset attribute rather than the <picture> element.

The <picture> element is used when you require art direction-based selection, like if you're using a wide shot for the large screen and a portrait crop on a narrow screen, for example. The thing about the <picture> element is that it's used in situations where we want a specific image to display at a specific breakpoint, hence there is no ambiguity in terms of image selection when using the <picture> element.

Which links back to my original question, are you using the same image for each screen width but simply in different sizes? If so, a normal img element with the srcset attribute would serve you much better.

For fluid-width images, srcset will be used with the w descriptor and sizes attribute. There are two values in the sizes attribute. The first is a media condition. The second is the source-size-value, which determines the width of the image given that particular media condition. Below is an example of the srcset syntax:

<img srcset="uswnt-480.jpg 480w, 
             uswnt-640.jpg 640w, 
             uswnt-960.jpg 960w,
             uswnt-1280.jpg 1280w" 
     sizes="(max-width: 400px) 100vw, 
            (max-width: 960px) 75vw, 
            640px" 
     src="uswnt-640.jpg" alt="USWNT World Cup victory">

Here, I’m telling the browser that for viewport widths up to 400 pixels, make the image 100% of the viewport width. At viewport widths up to 960 pixels, make the image 75% of the viewport width. And for everything above 960 pixels, make the image 640 pixels. The browser utilises the information from srcset and sizes to serve the image that best matches the stated conditions.

Full disclosure: I lifted a lot of this from an article I wrote previously on this topic

0
votes

This is what I wanted, 4 images flexed across a screen that are backed with multiple renditions of the JPG in order to save client bandwidth. Note the code is missing a src= attribute to make it valid.

body {
  display: flex;
  align-items: flex-start;
}
picture {
  margin: 1em;
}
<picture>
<img
srcset="https://placeholdit.imgix.net/~text?txtsize=89&txt=XSmall&w=150&h=63 150w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Small&w=300&h=126 300w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Medium&w=600&h=252 600w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Large&w=950&h=400 950w" sizes="calc(25vw - 2em)">
</picture>
<picture>
<img
srcset="https://placeholdit.imgix.net/~text?txtsize=89&txt=XSmall&w=150&h=63 150w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Small&w=300&h=126 300w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Medium&w=600&h=252 600w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Large&w=950&h=400 950w" sizes="calc(25vw - 2em)">
</picture>
<picture>
<img
srcset="https://placeholdit.imgix.net/~text?txtsize=89&txt=XSmall&w=150&h=63 150w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Small&w=300&h=126 300w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Medium&w=600&h=252 600w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Large&w=950&h=400 950w" sizes="calc(25vw - 2em)">
</picture>
<picture>
<img
srcset="https://placeholdit.imgix.net/~text?txtsize=89&txt=XSmall&w=150&h=63 150w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Small&w=300&h=126 300w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Medium&w=600&h=252 600w, https://placeholdit.imgix.net/~text?txtsize=89&txt=Large&w=950&h=400 950w" sizes="calc(25vw - 2em)">
</picture>

So I learnt several things:

  • How to flex images
  • picture.img is fine, you don't need to use the source element
  • learnt about vw the view port size width, which is like a percentage of the screen, but you must you absolute values when calculating margins, e.g. calc(25vw - 2em). 25vw = 1/4 of screen with the picture margins 1em+1em either side
  • this stuff is really complicated, this example doesn't even use break points, which I would suggest you avoid for your sanity!

It does exactly what I want it to do. It loads the appropriately sized and bandwidth efficient image. If resizing down, it doesn't load a smaller image, which I want. And when it scales up, it does fetch a larger higher resolution image, which I do want in order to avoid any ugly artefacts.

Result: Efficient transfer of several JPG renditions