How to fix CLS - cumulative layout shift

Hi all,

Although this page is under development, the home page is mostly finished. The problem I’m having is with the cumulative layout shift. Lighthouse is scoring it poorly and despite clues from the Lighthouse report and the Chrome extension Web Vitals, I can’t figure out how to improve it.

The dev site is here (you’ll need /home on the end, or you’ll end up on the coming soon page):

There’s an expanded version of the CSS here:
https://ramblaretreats.com/css/main-public.css

I’d be grateful for any advice.

Most of the layout shift is from the <section> which includes the photo of Graeme & Marianne. I suggest you try deleting the image’s width and height attributes from the HTML (in two places) and rely on the CSS.

You could also try deleting ‘auto’ from the CSS aspect-ratio (assuming all your candidate images have near-enough the same aspect ratio)

I’d be interested to see what happens as its always been my understanding that those attributes actually help to reduce layout shift as the browser can determine the aspect ratio before the image has fully downloaded and therefore allocate space correctly. Without them it has to fully download the image and then rearranges the space to fit resulting in a shift (even if you specify the dimensions in css).

This article seems to agree with my understanding and is a good read anyway as it mentions a lot of previous and current limitations.

TLDR:

The one change that is required of us web developers is to ensure we are providing width and height attributes in our markup. It’s a habit we shouldn’t really have gotten out of

2 Likes

I thought the same as @PaulOB, in fact the last change I made was to add width and height to all the source elements on the page, previously I only had them on the actual img. I added them after reading this article: Optimize Cumulative Layout Shift

Experiment 1

Added aspect-ratio and commented out max-width and width for
section.num-01 img
section.num-02 img

Ran Lighthouse 5 times in an incognito window

  1. CLS 0.743
  2. CLS 0.399
  3. CLS 0.507
  4. CLS 0.52
  5. CLS 0.618

Experiment 2

No CSS changes. Remove all width and height hints from source and img for the sections mentioned above.

Lighthouse performance now warns:
Image elements do not have explicit width and height

  1. CLS 0.345
  2. CLS 0.32
  3. CLS 0.322
  4. CLS 0.524
  5. CLS 0.502

Experiment 3

Added width and height back to the img elements, but not to source

  1. CLS 0.746
  2. CLS 0.51
  3. CLS 0.524
  4. CLS 0.745
  5. CLS 0.333

It feels like I have something fundamentally wrong, either with my layout or CSS :man_shrugging:

That article was written before CSS aspect-ratio became available.

That article says:

Always include width and height size attributes on your images and video elements. Alternatively, reserve the required space with CSS aspect-ratio or similar.

I wonder whether the layout shift is due to delay in downloading the file containing the aspect-ratio and other declarations: _home-url.scss.

EDIT Just tested one of my home pages with Lightbox. I get 100% performance score and zero cumulative layout shift. As images on the web page all have differing aspect ratios, I am including the aspect ratio within the HTML tag for each image: for example: style="aspect-ratio:490/220". All other CSS is within the <head> tag so no delay for a linked file.

1 Like

I’ve added the aspect-ratio inline and the section CLS values are much lower, but now the CLS for the main container is the killer. I’m getting a total CLS of 0.7~ consistently, with main being 0.5~

I guess it is due to the CSS and SCSS being in files, not in the <head> element.

Pingdom used to give a good insight into file loading times but it now seems you need to sign up to a 14 day free trial to get “timeline” displays: https://www.pingdom.com/#block_3.

(Incidentally, I wonder how Pingdom deals with srcset files).

How is the file _home-url.scss linked in? I have not found the link within your HTML.

1 Like

Chrome is showing me layout shifts for these items.

Screen Shot 2023-10-27 at 11.51.34

The layout shifts above because the hero hasn’t been shown yet and the space is not allocated to stop the layout shift. I see you have added an aspect ratio to the hero container but that does nothing because main has been set to display:flex and align-items:center and then the space collapses to nothing. If you remove the display:flex (or align-items:center) from main then the aspect ratio holds the page open for the hero container. (You can test this by deleting the image in the devtools and see what happens.)

It looks like you were only using flex there to centre the page so a margin:auto would suffice in this case.

If you then delete the image as a test you will see no shift in the layout.

In your left and right images chrome is showing a full row of text until the image appears so the whole layout shifts.

Screen Shot 2023-10-27 at 11.51.16

This is because you have not sized one or other of the flex containers and so they will try to be full width if either is not there.

If you size the picture container with a flex value and an aspect ratio then the text does not move even if the image is there or not and no layout shift occurs.

You will of course need to reset that value in your smaller media queries where you go full width etc.

Whether or not these are real issues is another matter :slight_smile:

1 Like

Thanks @PaulOB it’s performing much better after making those changes, for desktop it’s scoring 100 across the board now.

@Archibald I’m using Live Sass Compiler in VScode to compile the CSS. Normally I have the SCSS files in the web root directory, but in this project they’re above, so not visible. I might move them back to the web root though, better if they’re visible to all, especially for glitches like this!

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.