Addressing Cumulative Layout Shift (CLS)
Addressing Cumulative Layout Shift (CLS)
In recent weeks I’ve been investigating issues highlighted by Chrome’s Lighthouse tool relating to Cumulative Layout Shift (CLS). This post explains what CLS is, why it matters, and how I resolved it across a large image-heavy site.
What is CLS?
CLS occurs when elements on a webpage move unexpectedly while the page is loading. A common example is when you try to click a button, only for the page to shift at the last moment— resulting in clicking something else entirely.
This is more than just a minor annoyance; it directly impacts usability and is now a key metric in Google’s Core Web Vitals.
Why is this happening?
The primary cause of CLS on the Griffmonster Walks sites turned out to be images without defined dimensions.
When a browser encounters an image without width and height attributes,
it has no way of knowing how much space to reserve during the initial page layout.
- The browser renders the surrounding text first
- No space is reserved for the image
- The image loads later
- The layout shifts to accommodate it
The Key Fix: Defining Image Dimensions
Modern browsers use width and height attributes not as styling,
but as intrinsic size metadata. These values allow the browser to calculate the image’s
aspect ratio before the image has even downloaded.
Before (No Dimensions)
After (With Dimensions)
Without dimensions
<img src="image.jpg">
This results in no reserved space and visible layout shift.
With dimensions
<img src="image.jpg" width="800" height="600">
The browser now knows the aspect ratio and reserves space immediately, preventing layout shift entirely.
HTML vs CSS: Clearing Up the Confusion
At first, adding dimensions directly into HTML may feel like mixing structure and styling. However, these attributes serve a different purpose:
- HTML attributes define intrinsic dimensions (aspect ratio)
- CSS controls how the image is displayed
<img src="image.jpg" width="800" height="600" class="responsive">
.responsive {
width: 100%;
height: auto;
}
In this setup, CSS controls the final size, while HTML prevents layout shift.
Other Causes of CLS
While images were the main issue here, CLS can also be caused by:
- Ads or embedded content loading late
- Web fonts changing text layout
- Content injected dynamically above existing elements
- Third-party scripts modifying the page
Automating the Fix
With thousands of images across the site, manually adding dimensions wasn’t realistic. Instead, I built an automated pipeline using XSLT and Node.js.
The process
- Extract all image URLs from the generated HTML using XSLT
- Process the URLs with a Node.js script to fetch image dimensions
- Store the results in an XML configuration file
- Use a second XSLT to inject width and height attributes back into the HTML
- Redeploy the updated site via the Google API
Unexpected benefits
This process also exposed a number of issues that had gone unnoticed:
- Broken image URLs (404 errors)
- Typos in image paths
- Images hosted on unsupported external domains
Improving Image Loading
In addition to fixing layout shift, I improved loading behaviour using the
loading attribute:
<img loading="lazy">
This defers loading of images until they are needed (i.e. when they enter the viewport).
Important exception
The main image at the top of each page was excluded from lazy loading:
<img loading="eager" fetchpriority="high">
This ensures critical content loads as quickly as possible and avoids negatively impacting Largest Contentful Paint (LCP).
Responsive Images
To further optimise performance, I implemented responsive images using
srcset and sizes.
<img
src="image-800.jpg"
srcset="
image-400.jpg 400w,
image-600.jpg 600w,
image-800.jpg 800w"
sizes="(max-width: 450px) 400px, (max-width: 800px) 600px, 800px"
width="800"
height="600"
loading="lazy"
alt="Example image">
This allows the browser to select the most appropriate image size for the device, reducing bandwidth usage and improving load times.
Integrating the Updates into the Workflow
The workflow was adjusted to included this process such that all future deployments will include the changes.
Final Thoughts
By ensuring all images include intrinsic dimensions and improving loading behaviour, CLS issues across the site were significantly reduced.
The key takeaway is simple:
Providing intrinsic size information allows the browser to stabilise layout during initial rendering.
It’s a relatively small change with a significant impact on both performance metrics and real-world user experience.

0 comments:
Post a Comment