All guides · SEO

Responsive Images: Sharp, Undistorted, Right-Sized

Two image problems show up on almost every site that has grown over time: pictures that look stretched or squashed, and pictures that look soft or blurry on phones. Both are easy to see, make a site feel neglected, and are counted in Lighthouse’s Best Practices score.

Distorted images (aspect ratio)

An image has a natural aspect ratio, for example 1200 × 800 pixels (3:2). If CSS or HTML attributes display it in a box with a different ratio, say 300 × 300, the browser stretches it to fit.

The common causes:

  • width and height attributes that do not match the file, often copied from an older image;
  • CSS that sets both width and height of the image to fixed values;
  • a CMS that resizes uploads to a fixed box without cropping.

Fix: keep the attributes true to the file and let CSS scale proportionally:

<img src="/img/team.jpg" width="1200" height="800" alt="Our support team" />
img {
  max-width: 100%;
  height: auto;
}

The width and height attributes still matter: browsers use their ratio to reserve space before the image loads, which prevents layout shift. They describe the ratio, not the display size.

When the design really needs a fixed box (square thumbnails, card headers), crop instead of stretching:

.card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover; /* crop to fill the box */
  object-position: center;
}

Use object-fit: contain if the whole image must stay visible, with empty space around it.

Blurry images (resolution)

Phones and many laptops have screens with two or three device pixels per CSS pixel. An image shown 300 CSS pixels wide on such a screen needs 600 to 900 actual pixels to look sharp. Serve a 300-pixel file and the browser has to scale it up, which looks soft, especially for text and logos.

Sending one huge file to everyone is not the answer either: it wastes bandwidth on small screens and slows Largest Contentful Paint. Let the browser choose with srcset and sizes:

<img
  src="/img/hero-800.jpg"
  srcset="/img/hero-400.jpg 400w, /img/hero-800.jpg 800w, /img/hero-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, 50vw"
  width="1600"
  height="900"
  alt="Mountain trail at sunrise"
/>
  • srcset lists the available files and their real widths (400w).
  • sizes tells the browser how wide the image will be displayed: here the full viewport width on narrow screens, half of it otherwise.
  • The browser combines the two with the screen’s pixel density and downloads one suitable file.

For logos and icons, prefer SVG, which is sharp at any size. For fixed-size images such as avatars, the simpler density form works:

<img src="/img/avatar-64.png" srcset="/img/avatar-128.png 2x" width="64" height="64" alt="" />

WordPress adds srcset and sizes automatically to images inserted through the editor, using the sizes it generates on upload. Blurry images there usually mean a theme outputs a small thumbnail size, or the original upload was small. Upload at least twice the largest display width, and pick a larger image size in the block or theme settings.

Image CDNs and frameworks (Next.js Image, Astro Image and similar) can generate the variants and the markup for you.

How PerfoMetrix checks this

We read two Lighthouse audits from the PageSpeed Insights run the scan already makes: image-aspect-ratio (distorted images) and image-size-responsive (images with too few pixels for their display size on the test device’s screen). Google loads the page once in a mobile lab browser; we send no extra requests to your site. Each check needs attention when Lighthouse flags at least one image, and the report lists the first few. Lazy-loaded images that never entered the viewport during the run may not be tested.

Further reading: web.dev: responsive images and MDN: object-fit.

Last updated October 28, 2026