Images without explicit width and height attributes leave the browser unable to reserve space before the image loads. When the image arrives, content below jumps to make room - a behavior called Cumulative Layout Shift, one of the three Core Web Vitals.
Why this matters
Core Web Vitals is a trio of performance metrics Google began using as a ranking signal in 2021. Cumulative Layout Shift (CLS) measures how much elements jump while the page loads. A good CLS score is below 0.1, poor is above 0.25. Images missing dimensions are the most common cause of poor CLS.
Direct impact: pages with poor CLS rank lower, especially on mobile. Since Google's Page Experience update, sites that fail Core Web Vitals lost 5-30% of organic traffic. UX suffers too - a visitor about to click a link, only to have it shift away because an image loaded above it, abandons within seconds.
Secondary impact: First Contentful Paint (FCP) and Largest Contentful Paint (LCP) also suffer. The browser must recalculate layout each time a dimensionless image loads, slowing initial paint.
How to detect
Fastest path: PageSpeed Insights (https://pagespeed.web.dev/). Enter the site URL and check the CLS score. Under "Diagnostics" look for "Image elements do not have explicit width and height" - it lists every offending image.
Complementary check: in DevTools (F12) > Performance, record a page load. The "Layout Shift" track shows shift events - main content images are usually the culprit.
Third check: Google Search Console > Core Web Vitals reports URLs with poor CLS. A rising trend in poor URLs signals a CLS regression.
How to fix
WordPress 5.5+ adds width and height automatically to images served via core functions (the_post_thumbnail(), wp_get_attachment_image(), the Image block). If dimensions are missing, one of three causes is at play:
Cause one: a custom theme outputting <img> manually. Open the theme PHP files (Appearance > Theme File Editor) and grep for <img. Replace with wp_get_attachment_image() or the_post_thumbnail().
Cause two: a lazy-loading plugin stripping dimensions. Plugins like a3 Lazy Load, WP Rocket Lazy Load, or LiteSpeed Cache Lazy Load occasionally strip width/height. Open the plugin settings and verify it preserves dimensions. In WP Rocket: Media > LazyLoad - confirm dimension stripping is off.
Cause three: raw HTML in content. If you pasted <img src="..."> manually (HTML mode in the editor) it lacks dimensions. Replace with the core Image block.
Complementary CSS fix: use aspect-ratio to keep layout stable even when dimensions are not explicit.
img {
height: auto;
max-width: 100%;
}
.featured-image {
aspect-ratio: 16 / 9;
object-fit: cover;
}Common mistakes
First mistake: declaring dimensions in CSS instead of HTML attributes. CSS does not arrive at the same time as HTML, so the browser cannot reserve space during initial render. The width and height must live as HTML attributes.
Second mistake: using width: 100% in CSS without aspect-ratio. The browser knows the width but not the proportional height - CLS still triggers when the image loads.
Third mistake: invalid attribute values. width="100%" or height="auto" as HTML attributes are non-standard - they must be integer pixel values (width="800" height="600"). Use CSS for responsive sizing.
Fourth mistake: ignoring iframes. YouTube embeds, Google Maps, and other <iframe> elements also need explicit dimensions to prevent layout shift.
Verifying the fix
Re-run PageSpeed Insights and verify the warning is gone and CLS dropped below 0.1. In Search Console > Core Web Vitals, after 28 days of CrUX (Chrome User Experience Report) data, the report should reflect improvement. Run a Lighthouse audit in the browser and confirm the Performance score climbed.
fetchpriority="high" alongside the dimensions - it accelerates rendering and improves LCP simultaneously.