How to Fix CLS With Image and Video Size Attributes

How to Fix CLS With Image and Video Size Attributes

How to Fix CLS With Image and Video Size Attributes- 2026 Guide

Key Takeaway: Adding explicit width and height attributes to every <img> and <video> element is the single most impactful CLS fix available. It tells the browser exactly how much space to reserve before the media loads — eliminating the layout shift caused by images and videos popping into the page. This fix alone resolves CLS for the majority of websites and takes under an hour to implement.

You have seen it happen. You start reading a page. The text jumps down. A button moves. You accidentally click the wrong thing. That is Cumulative Layout Shift — and in most cases, an unsized image just loaded above you and pushed everything down.

Google measures this instability and uses it as a ranking signal. A CLS score above 0.1 is officially failing. Above 0.25 is Poor. And the number one cause of failing CLS scores across the web is images and videos without explicit dimensions.

The fix is two HTML attributes. This guide shows you exactly how to implement them on every platform — and what to do when you do not know the dimensions in advance.

If you are still diagnosing which Core Web Vitals are failing on your site, start with the complete Core Web Vitals fix guide before continuing here.

Why unsized images cause layout shift

When a browser builds a page, it does not wait for images to load before laying out content. It starts positioning elements immediately based on the HTML and CSS it has received.

If an image has no width and height attributes, the browser has no idea how tall it will be. So it allocates zero height. Text and other elements below the image are positioned as if the image does not exist.

Then the image loads. It is 400 pixels tall. The browser has to reflow the entire layout — pushing every element below the image down by 400 pixels. Everything shifts. Your CLS score records the shift.

This happens independently for every unsized image on the page. A page with five unsized images can have five separate layout shifts during loading — each one contributing to the final CLS score.

The browser has known the solution to this for decades. It is the width and height attributes — the same ones that existed in HTML4. Modern browsers use them to calculate the correct aspect ratio and reserve the right amount of space before the image loads. Zero reflow. Zero layout shift.

How browsers use width and height to prevent CLS

When you add width and height attributes to an <img> element, modern browsers do something clever. They calculate the intrinsic aspect ratio of the image and use it to reserve the correct amount of vertical space in the layout — even before the image has loaded a single byte.

html

<img src="hero.webp" width="1200" height="600" alt="Hero image">

With this markup, the browser knows:

  • The image will be 1200 units wide
  • The image will be 600 units tall
  • The aspect ratio is 2:1

When CSS makes the image responsive (width: 100%; height: auto), the browser maintains the 2:1 aspect ratio regardless of the actual rendered width. A 400px wide container reserves 200px of height. An 800px wide container reserves 400px of height. The space is always correct. No shift occurs when the image loads.

This is called the intrinsic size approach, and it works in all modern browsers — Chrome, Firefox, Safari, and Edge all support it.

The correct implementation

Basic fixed-size images

For images with a fixed display size:

html
<img
  src="/images/product.webp"
  width="800"
  height="600"
  alt="Product name"
>

Responsive images (most common use case)

For responsive images that scale with the viewport, add the attributes AND the CSS:

html
<img
  src="/images/hero.webp"
  width="1200"
  height="600"
  alt="Hero image"
  fetchpriority="high"
>
img {
  width: 100%;
  height: auto;
}

The height: auto in CSS, overrides the fixed height="600" attribute — the image scales proportionally. But the browser still uses the width and height attributes to calculate the aspect ratio and reserve the correct space. This combination is the correct modern approach.

Images inside containers

When images are inside a container with its own width constraints:

html
<div class="card">
  <img
    src="/images/card-image.webp"
    width="400"
    height="300"
    alt="Card image"
  >
</div>
css
.card {
  width: 100%;
  max-width: 400px;
}

.card img {
  width: 100%;
  height: auto;
}

The image scales to fill its container while maintaining the 4:3 aspect ratio defined by the attributes.

Video elements

The same principle applies to <video> elements. Always include width and height:

html

<video
  width="1280"
  height="720"
  controls
  preload="none"
  poster="/images/video-poster.webp"
>
  <source src="/videos/demo.mp4" type="video/mp4">
</video>

css
video {
  width: 100%;
  height: auto;
}

The The preload="none" attribute prevents the video from downloading before the user plays it — important for page speed. The poster attribute shows a static image until playback starts. Always add width and height to the poster image as well, if it is an <img> element.

When you do not know the image dimensions

The most common objection to adding width and height attributes is: "I do not know the dimensions in advance." This is common with user-uploaded content, CMS-managed images, and dynamically generated thumbnails.

Solution 1: The aspect-ratio CSS property

If you cannot add explicit width and height attributes, use aspect-ratio in CSS to reserve the correct proportional space:

css
.image-container {
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
  background: #f0f0f0; /* placeholder color while image loads */
}

.image-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
html
<div class="image-container">
  <img src="/images/dynamic-image.webp" alt="Dynamic image">
</div>

The container always reserves the correct 16:9 space. When the image loads inside it, there is no layout shift because the space was already allocated.

Use this approach for:

  • Blog post featured images with varying dimensions
  • User profile photos
  • Product images from a third-party inventory system
  • Any image where the dimensions are unknown at build time

Solution 2: Standardise your image dimensions

For content-managed sites, the most sustainable long-term fix is to standardise all images of the same type to the same dimensions. Product images all get cropped to 800×800. Blog featured images all get resized to 1200×630. Author photos all get resized to 200×200.

This lets you hardcode the correct width and height attributes for each image type in your templates — and it eliminates the "unknown dimensions" problem permanently.

Most CMS platforms and image optimisation services support automatic resizing and cropping on upload:

  • WordPress — set image sizes in functions.php using add_image_size()
  • Shopify — use Shopify's image URL parameters: image_url: width: 800, height: 800, crop: 'center'
  • Cloudinary — URL-based transformations: /w_800,h_600,c_fill/image.webp
  • imgix — URL parameters: ?w=800&h=600&fit=crop

Solution 3: JavaScript dimension detection (last resort)

For legacy systems where you cannot change the markup or standardise dimensions, use JavaScript to detect and set image dimensions after load — but before the image becomes visible:

javascript
document.querySelectorAll('img:not([width]):not([height])').forEach(img => {
  if (img.complete) {
    img.setAttribute('width', img.naturalWidth);
    img.setAttribute('height', img.naturalHeight);
  } else {
    img.addEventListener('load', () => {
      img.setAttribute('width', img.naturalWidth);
      img.setAttribute('height', img.naturalHeight);
    });
  }
});

This is a fallback — it does not prevent the initial layout shift because the dimensions are set after load. Use it only when you cannot implement Solutions 1 or 2. It does help browsers cache the correct dimensions for subsequent page loads.

Platform-specific implementation

WordPress

WordPress has handled this inconsistently over the years. Since WordPress 5.5, the core editor automatically adds width and height attributes to images inserted through the block editor. However, there are several scenarios where they may still be missing:

Check 1: Images in the Classic Editor Images inserted through the Classic Editor often lack width  height attributes, especially on older posts. Audit these by running PageSpeed Insights on your older content.

Check 2: Theme template images. Images hardcoded in theme templates (logo, hero image, sidebar images) need width and height added manually in the template file:

php

<img
  src="<?php echo get_template_directory_uri(); ?>/images/logo.webp"
  width="200"
  height="60"
  alt="<?php bloginfo('name'); ?>"
>

Check 3: Featured images in theme templates Use wp_get_attachment_image() instead of the_post_thumbnail() — it automatically includes width, height, and srcset attributes:

php
// Instead of:
the_post_thumbnail('large');

// Use:
echo wp_get_attachment_image(get_post_thumbnail_id(), 'large');

Check 4: WooCommerce product images. WooCommerce product images are output through its own template system. In your theme's woocommerce/single-product/product-image.php, ensure images use wc_get_product_attachment_props() which returns dimensions you can add as attributes.

Plugin approach: The Smush and Imagify plugins both include options to automatically add missing width and height attributes to images sitewide. Enable this in their settings for the fastest fix across all existing content.

Shopify

Shopify's Liquid templating system gives you access to image dimensions through the image object:

liquid
{%- assign image = section.settings.hero_image -%}
{%- if image != blank -%}
  <img
    src="{{ image | image_url: width: 1200 }}"
    width="{{ image.width }}"
    height="{{ image.height }}"
    alt="{{ image.alt | escape }}"
    loading="{% if forloop.first %}eager{% else %}lazy{% endif %}"
  >
{%- endif -%}

For product images in the collection and product templates:

liquid
{%- for image in product.images -%}
  <img
    src="{{ image | image_url: width: 800 }}"
    width="{{ image.width }}"
    height="{{ image.height }}"
    alt="{{ image.alt | escape }}"
    loading="{% if forloop.first %}eager{% else %}lazy{% endif %}"
  >
{%- endfor -%}

Shopify's An image object always has .width and .height properties — use them consistently in all image output throughout your theme.

For responsive images in Shopify, use the image_tag filter which automatically includes dimensions:

liquid
{{ image | image_url: width: 1200 | image_tag: loading: 'lazy', widths: '400, 800, 1200' }}

Next.js

If you are using next/image, width, and height are required props — the component will throw an error if you omit them:

jsx
import Image from 'next/image';

export default function ProductCard({ image }) {
  return (
    <Image
      src={image.src}
      width={800}
      height={600}
      alt={image.alt}
      priority={false}
    />
  );
}

For images with unknown dimensions, use the fill prop with a sized container:

jsx

<div style={{ position: 'relative', width: '100%', aspectRatio: '16/9' }}>
  <Image
    src={image.src}
    fill
    style={{ objectFit: 'cover' }}
    alt={image.alt}
  />
</div>

The fill prop makes the image fill its parent container. The aspectRatio container reserves the correct space. This is the Next.js equivalent of the aspect-ratio CSS approach.

Blogger

Blogger's post editor automatically adds width and height to images inserted through the image upload tool. However, images pasted from external URLs or added through HTML view often lack these attributes.

For images in Blogger posts:

  1. Switch to HTML view in the post editor
  2. Find <img tags without width and height
  3. Add the attributes manually

For your Blogger theme's template images — logo, header image, sidebar images — edit them in Theme → Edit HTML and add width and height directly to the <img> tags.

If your Blogger site is experiencing broader performance issues beyond CLS, see why your Blogger page speed is low for a comprehensive performance walkthrough.

Images vs videos — key differences

Images and videos both benefit from explicit dimensions, but there are important differences in implementation:

Images Videos
Attributes width and height on <img> width and height on <video>
CSS height: auto for responsive scaling height: auto for responsive scaling
Preloading fetchpriority="high" for LCP image preload="none" to prevent auto-download
Placeholder The browser uses the aspect ratio Browser uses aspect ratio + poster image
Lazy loading loading="lazy" for below-fold images No native lazy loading — use Intersection Observer

For videos specifically, always include a poster attribute pointing to a static image. This gives users something to see while the video loads and prevents the video container from appearing as a blank space during load.

If you also want to understand how unsized images connect to your LCP score — since the LCP element is often an image — see what is a good LCP score for the full breakdown of how image loading affects LCP timing.

How to audit your site for missing dimensions

Automated audit with PageSpeed Insights

Run PageSpeed Insights on your key pages. Under Diagnostics, look for "Image elements do not have explicit width and height". This lists every image on the page, missing dimensions, and its CLS contribution.

Browser console audit

Open your browser console on any page and run this snippet to find all images missing dimensions:

javascript
const unsizedImages = Array.from(document.images).filter(img =>
  !img.hasAttribute('width') || !img.hasAttribute('height')
);

console.log(`Found ${unsizedImages.length} images without explicit dimensions:`);
unsizedImages.forEach(img => console.log(img.src));

This instantly lists every image on the current page that is missing width or height attributes — giving you a prioritised fix list.

Screaming Frog audit (for full site)

For a complete site audit:

  1. Open Screaming Frog
  2. Go to Configuration → Custom → Search
  3. Add a custom search for images without width attributes
  4. Crawl your site
  5. Export the list of affected URLs

This gives you a complete list of every page on your site with unsized images — useful for prioritising which pages to fix first based on traffic.

Connecting image dimensions to your full CLS strategy

Fixing image and video dimensions resolves the most common cause of CLS — but it is not the only cause. Once your images are sized correctly, check for these remaining CLS sources:

  • Web fonts swapping late — preload key fonts and use font-display: optional
  • Dynamically injected content — give ad slots and cookie banners reserved space
  • Layout-affecting animations — replace top/left animations with transform
  • Unsized iframes — wrap embeds in aspect-ratio containers

For the complete guide to all CLS causes and fixes, see what causes cumulative layout shift.

Fixing image dimensions also has a secondary benefit for LCP. When the browser knows the image dimensions in advance, it can calculate layout without waiting for the image to load — which reduces the time spent in the element render delay phase of LCP. Combined with preloading your LCP image, fixing server response time, and eliminating render-blocking resources, sized images complete the core fix stack for both LCP and CLS simultaneously.

Frequently asked questions

Q1. Do width and height attributes need to match the actual image file dimensions? 

They should match the natural dimensions of the image file for the best result, but what matters most is that the aspect ratio is correct. If your image file is 2400×1600 but you set width="1200" height="800", the aspect ratio to be the same (3:2), the browser will reserve the correct proportional space. The image will still render correctly at any responsive size.

Q2. Will adding width and height break my responsive images? 

No, as long as you have height: auto in your CSS. The CSS height: auto overrides the HTML height attribute for display purposes while preserving the aspect ratio information the browser uses for space reservation. This combination is the standard modern approach and works across all browsers.

Q3. My images are added by users and I cannot control their dimensions. What do I do?

Use the aspect-ratio CSS approach to the image container. Set a standard aspect ratio (16:9, 4:3, or 1:1, depending on your content) and use it object-fit: cover on the image. This reserves consistent space for every image regardless of its actual dimensions.

Q4. Does this fix apply to background images set via CSS? 

No. CSS background images do not use width  height HTML attributes. For CSS background images, use a padding-bottom hack or aspect-ratio on the container element to reserve space. The background image itself does not cause CLS if the container has a defined height.

Q5. Why does my CLS score still show shifts after adding dimensions to all images? 

Image dimensions are the most common CLS cause, but not the only one. Other common causes include late-loading web fonts, dynamically injected banners and ads, and JavaScript that modifies the DOM after the initial render. After fixing image dimensions, check for these other causes using Chrome DevTools Layout Shift Regions (under the Rendering panel).

Q6. Does lazy loading affect CLS if I add width and height?

No — if width and height are present, lazy loading does not cause CLS. The browser reserves the correct space based on the dimensions before the image loads, regardless of when the image actually loads. Always add both width/height attributes AND loading="lazy" to all below-fold images.

Q7. How do I fix missing dimensions on hundreds of existing blog posts? 

For WordPress, use the Smush or Imagify plugin's bulk fix feature, which automatically adds missing dimensions sitewide. For other platforms, use a script or crawl tool to identify affected URLs, then either fix them in bulk through the database or use a JavaScript snippet that detects and applies dimensions client-side as a temporary measure while you fix the markup properly.

Summary

Adding width and height attributes to every <img> and <video> Element is the highest-impact, lowest-effort CLS fix available. It tells the browser exactly how much space to reserve before media loads — eliminating the layout shift that occurs when unsized images push content down.

The implementation for responsive images:

html

<img
  src="/image.webp"
  width="1200"
  height="600"
  alt="Description"
>
css
img {
  width: 100%;
  height: auto;
}

When dimensions are unknown, use aspect-ratio CSS on the container. When dimensions can be standardised, do so at the CMS or image pipeline level.

Fix image dimensions first. Then work through the remaining CLS causes. Then check your LCP and INP scores. The complete Core Web Vitals guide covers everything in one place.

Author Image

Hardeep Singh

Hardeep Singh is a tech and money-blogging enthusiast, sharing guides on earning apps, affiliate programs, online business tips, AI tools, SEO, and blogging tutorials. About Author.

Previous Post