Cumulative Layout Shift (CLS) is one of Google’s Core Web Vitals. A Layout Shift is an unexpected movement of the pages content, which can cause a poor user experience. The CLS metric is a score on how much the page shifts around. Too high a value and Google will deem the page a poor experience.
A common reason for a Layout Shift is when an image suddenly appears and push the content underneath it down. This could be a large banner at the top of a page, which alone could cause a big enough shift for a page to fail.
Somtimes the fix can be simple. If the image is shown at a specific size you can just specify its width and height in the img tag:
<img src="image.jpg" width="912" height="684" alt="I'm always shown with the same dimensions" />
However, quite often an image is made responsive. e.g. it’s always the full width of the page. That’s how the example above was written:
<img src="image.jpg" style="width: 100%;" alt="I'm 100% width but I'm not telling you how tall I am"/>
In this case we don’t want to have a fixed width, we want it to match the width of its container.
There are two ways to let the browser know what space to allocate in advance…
Using aspect-ratio to size a responsive image
This is only supported by newer browsers at the moment. But I think it is a neat solution, so I will share.
The browser can already calculate the width of the image from the width = 100% requirement. If the browser knows the aspect ratio of the image it can then work out the height.
aspect-ratio = width / height
If you have any two of the variables you can work out the third.
Recent browsers support the aspect-ratio CSS property. So you can apply a width and aspect-ratio, and the browser can work out the height:
<img src="image.jpg" style="aspect-ratio: 912 / 684; width: 100%;" alt="height = width / aspect-ratio"/>
Notice that I can use a formula to work out the aspect ratio from the images native width and height.
It’s worth pointing out that you should not set a height in this case (or set it to auto). If no height is provided it will work it out from the other two.
As this is only available on newer browsers, we will probably go with the alternate solution…
Using height auto to size a responsive image
In this scenario we help the browser work out the aspect-ratio by providing both the native height and width in the img attributes. The browser will use them to calculate the aspect-ratio. We then override those settings in CSS so that it uses the new width and previously worked out aspect-ratio to size the image. Setting height to auto is how we tell it to not use the original height, but calculate it from the other values.
<img src="image.jpg" width="912" height="684" style="width: 100%; height: auto;" alt="height auto solution"/>
This solution is compatible with more browsers, but I feel it’s a little harder to understand.
Both cases work just as well. The text does not move and Google is happy.