HTML5’s responsive image implemention is missing a way to handle aspect ratios

HTML5’s responsive image implementation provides a fantastic tool to address the performance issue of image-heavy websites. But there is a crucial feature that is still missing.

If you don’t know how responsive images work I recommend you read Eric Portis’s article on Smashing Magazine as I won’t go into the mechanics in detail.

However, to remind you, a simple markup would look like this:

sizes="(min-width: 800px) 800px,
  img/IMG_7252-3.jpg 640w,
  img/IMG_7252-2.jpg 1130w,
  img/IMG_7252-1.jpg 1527w,
  img/IMG_7252-0.jpg 1750w"
width="1130px" height="848px" src="img/IMG_7252-2.jpg" 
alt="Lorem ipsum dolor sit amet" />

In the current syntax, we define our image constraints in width only. This is mostly fine since most layouts are constrained by the width of the website or the width of the device. In fact, this is how we have done responsive images in CSS:

img {
  width: 100%;
  height: auto;

But wait, wasn’t there a good reason to define an absolute height of an image? Yes! It all comes down to the rendering of the webpage. When a browser loads an image it doesn’t yet know the dimensions of it. In many cases however, since images are not render-blocking, the rest of the website is already rendered while the image is still loading.

A normal none responsive image with fixed width and height and a grey background. It's not yet loaded.
A normal none responsive image with fixed width and height and a grey background set via CSS. The image is not yet loaded.

At this stage, the browser knows two things about the image: width: 100%; and height: auto;. The width can be calculated by the browser since it is aware of the width of the parent container. The height, however, is relative to the aspect ratio of the image which the browser can only learn once the image is loaded. For now, the browser has to guess the height and it always gets it wrong. (Firefox guess is square format, while chrome sets the initial height to 0px). Once the browser learns the actual height of the image it has to redraw it. This redraw usually forces a bunch of other elements to be redrawn as well. You may have noticed this on bad news sites, you’re already reading an article and suddenly all the text starts to jump around.1

A responsive image with variable height in chrome. Chrome sets the initial height to zero.
A responsive image with variable height in chrome. I marked the position of the image in red. Chrome sets the initial height to zero.
The image pushes the text to the bottom once it's loaded.
The image pushes the text to the bottom once it's loaded.

There is a nifty trick to set the image height based on the container width and the aspect ratio. But it’s a rather heavy investment since it requires calculating the aspect ratio yourself and injecting it in the HTML markup.

How could this be fixed?

There are discussions dating back to 2014 addressing this very issue. And it seems that an additional height-based value might be finally coming.

srcset=" 150w 100h

But will this solve the aspect ratio issue which we just discussed? We will have to see. If you want to help move things along you could check out the discussion on GitHub. The more interest this issue receives the better.

  1. In theory, this could also happen on this very site. In practice, however, it doesn’t. Images are loaded with the first batch of requests