Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.
ImagesHigh

Set explicit width and height on images

All <img> elements have explicit width and height attributes so browsers can reserve space before the image loads, preventing layout shift.

Utilities
Quick take
Typical fix time 10 min
  • Reserve findings for meaningful content images; decorative micro-SVGs or ornament-only assets are low-priority exceptions when CSS already reserves stable space
  • Example low-risk exception: `<img src="/divider.svg" alt="" aria-hidden="true">` should not be flagged on its own without evidence of visible layout shift
  • Always set `width` and `height` attributes on `<img>` matching the image's intrinsic dimensions
  • Pair with `height: auto` in CSS to keep the image fluid while preserving the aspect ratio
  • Missing dimensions are the leading cause of Cumulative Layout Shift (CLS) from images
  • Browsers derive `aspect-ratio` from these attributes—do not set arbitrary placeholder values
Why it matters: Images without explicit dimensions are the most common cause of Cumulative Layout Shift (CLS), a Core Web Vitals metric. When images load and cause layout jumps, users accidentally click the wrong element—a frustrating experience that Google penalises in search rankings. A CLS score above 0.1 is considered 'needs improvement'; above 0.25 is 'poor'.

Rule Details

Browsers need to know an image's dimensions before it downloads so they can reserve the correct space in the layout. Without width and height attributes, the page jumps when images load—this is measured as Cumulative Layout Shift (CLS).

Code Examples

<!-- ❌ Bad: Browser reserves 0 height until image loads, then shifts layout -->
<img src="product.jpg" alt="Red running shoes">
 
<!-- ✅ Good: Browser reserves 600×400 space immediately -->
<img
  src="product.jpg"
  alt="Red running shoes"
  width="600"
  height="400"
>

Add CSS to keep the image responsive while the HTML attributes reserve space:

img {
  max-width: 100%;
  height: auto; /* Overrides the height attribute for responsive scaling */
}

Why It Matters

Images without explicit dimensions are the most common cause of Cumulative Layout Shift (CLS), a Core Web Vitals metric. When images load and cause layout jumps, users accidentally click the wrong element—a frustrating experience that Google penalises in search rankings. A CLS score above 0.1 is considered 'needs improvement'; above 0.25 is 'poor'.

How Browsers Use These Attributes

Modern browsers (Chrome 79+, Firefox 71+, Safari 15+) automatically derive the aspect-ratio from the HTML width and height attributes:

/* The browser internally applies this rule when width/height are present */
img {
  aspect-ratio: attr(width) / attr(height);
}

This means reserving space works even before the CSS loads, provided the HTML attributes are present.

Responsive Images with Correct Dimensions

For responsive images using srcset, set dimensions matching the largest intrinsic size (or the 1x size). The browser will scale down using CSS but reserve space proportionally.

<!-- ✅ Dimensions on the <img>, not on <source> elements -->
<picture>
  <source
    type="image/avif"
    srcset="hero-800.avif 800w, hero-1600.avif 1600w"
    sizes="(max-width: 800px) 100vw, 800px"
  >
  <source
    type="image/webp"
    srcset="hero-800.webp 800w, hero-1600.webp 1600w"
    sizes="(max-width: 800px) 100vw, 800px"
  >
  <img
    src="hero-800.jpg"
    srcset="hero-800.jpg 800w, hero-1600.jpg 1600w"
    sizes="(max-width: 800px) 100vw, 800px"
    alt="Hero image"
    width="1600"
    height="900"
  >
</picture>

Dynamic Images

For images with dynamic dimensions, calculate from the known aspect ratio.

// React: Preserve aspect ratio from known values
interface AspectImageProps {
  src: string
  alt: string
  aspectRatio: '16/9' | '4/3' | '1/1'
}
 
const ASPECT_DIMENSIONS = {
  '16/9': { width: 1600, height: 900 },
  '4/3': { width: 800, height: 600 },
  '1/1': { width: 800, height: 800 },
}
 
function AspectImage({ src, alt, aspectRatio }: AspectImageProps) {
  const { width, height } = ASPECT_DIMENSIONS[aspectRatio]
 
  return (
    <img
      src={src}
      alt={alt}
      width={width}
      height={height}
      style={{ maxWidth: '100%', height: 'auto' }}
    />
  )
}

Next.js

Next.js <Image> requires width and height props (or fill) and handles layout shift prevention automatically.

import Image from 'next/image'
 
// next/image enforces dimensions at compile time
function ProductCard({ product }) {
  return (
    <Image
      src={product.imageUrl}
      alt={product.name}
      width={600}
      height={400}
      // sizes tells the browser what display size to expect
      sizes="(max-width: 768px) 100vw, 600px"
    />
  )
}

Implementation Notes

When intrinsic dimensions are not known at author time, reserve space with a stable aspect ratio instead of letting the image collapse.

.image-frame {
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
}
 
.image-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Background images need the same reservation strategy on the container:

.hero {
  aspect-ratio: 21 / 9;
  background: center / cover no-repeat url('/hero.jpg');
}

Measuring CLS Impact

// Measure CLS using the web-vitals library
import { onCLS } from 'web-vitals'
 
onCLS(metric => {
  console.log('CLS score:', metric.value)
 
  // Log which elements caused the shift
  metric.entries.forEach(entry => {
    console.log('Shift sources:', entry.sources)
  })
})

Tools & Validation

document.querySelectorAll('img').forEach(img => {
  if (!img.hasAttribute('width') || !img.hasAttribute('height')) {
    console.warn('Image missing dimensions:', img.currentSrc || img.src)
  }
})
  • Use Lighthouse or PageSpeed Insights to confirm missing dimensions show up as real CLS contributors.
  • In Chrome DevTools, enable Layout Shift Regions in the Rendering panel to verify the fix stops movement rather than only changing markup.

Verification

Automated Checks

  • Run Lighthouse — the "Image elements do not have explicit width and height" audit flags missing attributes
  • Run PageSpeed Insights — CLS is reported from real user data
  • Use Chrome DevTools → Performance panel → record page load, look for layout shift markers

Manual Checks

  • Install the Web Vitals Chrome extension to see CLS scores in real time
  • CSS background images — dimensions are controlled via background-size and container sizing; HTML attributes do not apply
  • SVG icons inline or as <img> where width/height CSS is set absolutely (e.g., width: 24px; height: 24px)—layout shift risk is negligible
  • Tiny decorative SVG dividers or ornaments where the snippet already shows stable CSS sizing and the asset carries no content meaning
  • Images in fixed-height containers where overflow is hidden—the container already reserves space regardless of image dimensions

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Scan all <img> elements in the codebase. Identify any that are missing either the width or height attribute. Also check <source> elements inside <picture>—dimensions should be on the <img> fallback. Report each image missing dimensions with its file path and line number. Note: SVG icons under 32px, tiny decorative SVG ornaments with stable CSS sizing, and images loaded as CSS backgrounds are exempt.

Fix

Auto-fix issues

For each <img> missing width/height: 1) Add the intrinsic pixel dimensions as attributes (e.g., width="800" height="450"). 2) Use CSS max-width: 100% and height: auto on the element to keep it responsive. 3) The attribute values must match the image's intrinsic aspect ratio—do not set arbitrary numbers. 4) For dynamically sized images, calculate the aspect ratio and use the CSS aspect-ratio property as a fallback. 5) Skip purely decorative micro assets when the snippet already shows stable sizing and there is no evidence of layout shift risk. Show the before and after HTML for each fixed image.

Explain

Learn more

Explain why width and height attributes on <img> prevent Cumulative Layout Shift (CLS). When a browser parses HTML, it does not yet know an image's dimensions—without explicit attributes, the browser initially renders a 0-height placeholder, then jumps the layout when the image loads. With width and height set, the browser calculates the aspect ratio from the attributes and reserves space immediately, eliminating the shift. This became especially important as modern browsers use the aspect-ratio CSS property derived from these HTML attributes.

Review

Code review

Review image assets, markup, and delivery configuration related to Set explicit width and height on images. Flag exact files or components where format choice, sizing, or loading behavior violates the rule, and describe how to confirm the fix in DevTools.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

Lighthousedeveloper.chrome.comTool
PageSpeed Insightspagespeed.web.devTool

Rules that often go hand-in-hand with this one.

Serve images at the correct display size

Images are not significantly larger than their display dimensions—serving a 2000px image for a 400px container wastes bandwidth and hurts LCP.

Images
Lazy load offscreen images

Images below the visible viewport use loading="lazy" to defer download until the user scrolls near them, reducing initial page load time.

Images
Implement lazy loading for offscreen content

Images and heavy resources below the fold are lazy loaded to improve initial performance.

Performance
Minimize cumulative layout shift

Page maintains visual stability with a CLS score below 0.1, preventing unexpected content shifts during load.

Performance

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385