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:
widthandheightattributes that do not match the file, often copied from an older image;- CSS that sets both
widthandheightof 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"
/>
srcsetlists the available files and their real widths (400w).sizestells 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.