Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Responsive images without layout reflow when they load

To have responsive images that scale down proportionally on a small screen, I currently use max-width: 100%; (or a fixed max width). As opposed to specifying a fixed size, this has a terrible downsize in that when the page is loading, the browser allocates no space for the image and can only do that after it starts downloading it. This causes a lot of layout reflows and a bad experience before all images are loaded.

This seems like it could be easily fixed - after all, I just have to tell the browser what the real size is so that it can figure out the aspect ratio and the final size before downloading it. First, I was wondering if that's what the width and height html attributes are for, but I know that that's not their purpose as they can be used to rescale the image and change the final size.

What I really want is something like "srcwidth" and "srcheight" that would tell the browser the actual size of the image file so that it doesn't have to load before knowing the aspect ratio to make use of the max-width styling. But from what I could find, there is no such thing like these attributes. Is there really no way to achieve this?

I tried using the actual width and height html attributes in this way and then overriding it with CSS, but browsers simply don't care about that.

like image 273
Neme Avatar asked Aug 24 '17 19:08

Neme


1 Answers

The most common way I've seen this addressed is to put all your images in containers and use the padding-bottom property to "pre-allocate" the height.

<div class="responsive-container">
    <img src="image.jpg"/>
</div>

To do this, you need to know the aspect ratio of the image to calculate the padding.

Using the Aspect Ratio to work out the height

For example, for an aspect ratio of 16:9 (e.g. 800 x 450px) the height is 56.25% of the width so that will be the value for the padding.

.responsive-container {
    width: 100%;
    padding-bottom: 56.25%; /* 9/16 = aspect ratio of image */
    position: relative;
    height: 0;
    overflow: hidden;
}

.responsive-container img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
}

Different Aspect Ratios

If your images will have different aspect ratios, but you will still know then ahead of time, you set up different classes for each, e.g.

.responsive-container {
    width: 100%;
    position: relative;
    height: 0;
    overflow: hidden;
}

.ratio-16-9{
    padding-bottom:56.25%; /* 9/16*100 */
}

.ratio-4-3{
    padding-bottom:75%; /* 3/4*100 */
}

.ratio-1-1{
    padding-bottom:100%; 
}

And to use it in the html:

<div class="responsive-container ratio-16-9">
    <img src="image.jpg"/>
</div>

Calculate height dynamically

Finally, if you want the CSS to calculate the height dynamically for each image, you can use CSS calc() to calculate the height like this:

calc((image_height/image_width)*100%)

So your CSS would be: .responsive-container { width: 100%; position: relative; height: 0; overflow: hidden; }

And you use it like this:

<div class="responsive-container" style="padding-bottom: calc((426/640)*100%);" >
    <img src="image.jpg"/>
</div>

References

  • Responsive images – how to prevent reflow
  • Responsive Images Without Browser Reflow
  • MDN Web Docs for CSS calc()
like image 139
FluffyKitten Avatar answered Oct 13 '22 02:10

FluffyKitten