简体   繁体   中英

Responsive images when image rendering size in relation to screen width is unknown

I have a CMS (TYPO3) which currently outputs plain <img> tags. To make it responsive, I want to add srcset attributes with different size versions of the image.

Which leads us to the problem: With the sizes attribute, I can tell the browser what rendering size to assume when choosing the image version. I can give the rendering size absolutely (in px , em , etc.) or as a percentage of viewport width (in vw ). However I cannot tell the browser to assume the image will have its parent's width (in % ).

If I knew the parent width beforehand, I could just add it to the sizes attribute, if need be with some media conditions if the parent size changes due to a responsive layout (like Bootstrap columns).

Alas, I'm extending a CMS and have no control over layout or content, like:

  • the page container width
  • the number of columns
  • design breakpoints
  • column paddings and gutter widths
  • any nesting of columns within columns
  • any other paddings

Collecting all this information - just to find out how big the image parent is going to be - is next to impossible.

Any ideas on how I can get a responsive image that delivers the ideal size even though I don't know the final image rendering width (=parent width) at server side (neither in px nor vw )?

Though I prefer static solutions, I'm also open to JavaScript based ideas, given they fallback gracefully.

Edit : My question boils down to: is there some mechanism that can replace the sizes="100%" which is not in the standard "to avoid confusion what it would be relative to" ?

Edit : My current solution is JS-based:

// this, plus some code to prevent image loading before this is executed
$('img[srcset]').each(function() {
  $(this).attr('sizes', $(this).parent().width() + 'px');
})

I would like to not have to rely on JS to do this.

Two options:

Use srcset

Your use case is exactly what srcset was designed for. The <source> image sizes are known ahead of time; the container size is known at run time; you define pixel ranges exactly like CSS @media queries to tell the browser which <source> to use for a given container size.

The media query is relative to the viewport, not the container (as with CSS media queries) so you do have to do some math to decide which image you want to use for a container's expected size relative to that viewport. (I believe the reason for this complexity is so you can set images depending on screen density as well, but don't quote me on that.)

The idea is to set the size of the image externally, relative to a container, then use srcset to select an image appropriate for that container's expected size given that viewport size.

(StackOverflow's code snippet makes this difficult to see because it draws the sample inside a fixed-size frame; the most you can see is the image source not changing when you resize the div, which maybe isn't the most compelling demo ever. To try out the viewport resize you'll need to copy the code into a new window).

 .container { border: 1px solid; width: 50%; height: 150px; resize: horizontal; overflow:auto; }
 <div class="container" resizable> <picture> <source media="(max-width: 100px)" srcset="http://via.placeholder.com/100x150"> <source media="(max-width: 200px)" srcset="http://via.placeholder.com/200x150"> <source media="(max-width: 300px)" srcset="http://via.placeholder.com/300x150"> <source media="(max-width: 400px)" srcset="http://via.placeholder.com/400x150"> <source media="(max-width: 500px)" srcset="http://via.placeholder.com/500x150"> <source media="(max-width: 600px)" srcset="http://via.placeholder.com/600x150"> <source media="(max-width: 700px)" srcset="http://via.placeholder.com/700x150"> <source media="(max-width: 800px)" srcset="http://via.placeholder.com/800x150"> <img src="http://via.placeholder.com/10x10" width="100%"> </picture> </div>

Browser support is currently incomplete (IE and Edge are, as usual, the culprits) but polyfills exist.

Use background-image

...which can be changed using media queries.

@media screen and (min-width: 501px) {
  .container {
    background-image: url('big.jpg');
  }
}
@media screen and (max-width: 500px) {
  .container {
    background-image: url('small.jpg');
  }
}

This is universally supported, but requires that your CMS be able to generate CSS rules along with the HTML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM