Fix Incorrect Image Aspect Ratio for Better Best Practices Score

Display images with their natural aspect ratio to prevent distortion. Stretched or squished images look unprofessional.
Harlan WiltonHarlan Wilton3 min read Published

When an image's display dimensions don't match its natural aspect ratio, it gets stretched or squished. Faces look wrong. Products look unprofessional. Users notice.

What's Happening

You have an image with natural dimensions of 1200x800 (aspect ratio 1.5:1), but you're displaying it at 400x400 (aspect ratio 1:1). The browser has three choices: stretch it, squish it, or crop/contain it. Without explicit object-fit instructions, it stretches.

Lighthouse compares the displayed aspect ratio to the natural aspect ratio. If they differ by more than a couple pixels (accounting for rounding), the audit fails. It only checks images using object-fit: fill (the default) because other values intentionally override aspect ratio behavior.

Diagnose

Chrome DevTools

  1. Right-click the distorted image, select Inspect
  2. Check the element's rendered dimensions vs natural dimensions:
// Select the image element first
const img = $0
console.log({
  natural: `${img.naturalWidth}x${img.naturalHeight}`,
  displayed: `${img.clientWidth}x${img.clientHeight}`,
  naturalRatio: (img.naturalWidth / img.naturalHeight).toFixed(2),
  displayedRatio: (img.clientWidth / img.clientHeight).toFixed(2)
})

If the ratios don't match, that's your problem.

Find All Distorted Images

document.querySelectorAll('img').forEach((img) => {
  if (!img.naturalWidth || !img.naturalHeight)
    return
  if (img.clientWidth < 5 || img.clientHeight < 5)
    return

  const naturalRatio = img.naturalWidth / img.naturalHeight
  const displayedRatio = img.clientWidth / img.clientHeight
  const diff = Math.abs(naturalRatio - displayedRatio)

  if (diff > 0.05) {
    console.warn('Aspect ratio mismatch:', img.src, {
      natural: `${img.naturalWidth}x${img.naturalHeight} (${naturalRatio.toFixed(2)})`,
      displayed: `${img.clientWidth}x${img.clientHeight} (${displayedRatio.toFixed(2)})`
    })
  }
})

Fix

1. Match Container to Image Ratio

The cleanest fix: make the display dimensions match the natural aspect ratio.

<!-- Image is 1200x800 (1.5:1 ratio) -->
<!-- Bad: forcing into a square -->
<img src="/photo.jpg" style="width: 400px; height: 400px;">

<!-- Good: maintaining ratio -->
<img src="/photo.jpg" style="width: 400px; height: 267px;">

<!-- Better: let height auto-calculate -->
<img src="/photo.jpg" width="1200" height="800" style="width: 400px; height: auto;">

With width and height attributes, browsers calculate the aspect ratio automatically:

img {
  max-width: 100%;
  height: auto;
}

2. Use object-fit for Fixed Containers

When you need a specific container size regardless of image ratio, use object-fit:

.thumbnail {
  width: 200px;
  height: 200px;
  object-fit: cover; /* Crop to fill, maintain ratio */
}

.product-image {
  width: 100%;
  height: 300px;
  object-fit: contain; /* Fit inside, maintain ratio, may letterbox */
}

object-fit values:

  • cover - Fill container, crop excess (most common for thumbnails)
  • contain - Fit inside container, letterbox if needed
  • fill - Stretch to fill (default, causes distortion)
  • none - Natural size, crop if larger
  • scale-down - Like contain but never upscales
<div class="avatar">
  <img src="/user.jpg" alt="User" style="width: 100%; height: 100%; object-fit: cover;">
</div>
.avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  overflow: hidden;
}

3. Use aspect-ratio for Responsive Containers

Let CSS maintain the ratio while the container scales:

.video-thumbnail {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.video-thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

The container maintains 16:9, and object-fit: cover handles any image that doesn't match exactly.

4. Crop Images at Source

If every image in a gallery should be square, crop them to square before uploading rather than relying on CSS:

// Server-side with Sharp
import sharp from 'sharp'

sharp('input.jpg')
  .resize(400, 400, {
    fit: 'cover',
    position: 'attention' // Smart crop
  })
  .toFile('output-square.jpg')

This gives you control over what gets cropped rather than leaving it to CSS.

Framework Examples

Nuxt - Use NuxtImg with fit prop:
<template>
  <NuxtImg
    src="/photo.jpg"
    width="400"
    height="400"
    fit="cover"
    alt="Photo"
  />
</template>
For containers with fixed aspect ratio:
<div class="aspect-square">
  <NuxtImg src="/photo.jpg" class="w-full h-full object-cover" />
</div>
Next.js - next/image with fill and objectFit:
<div className="relative w-48 h-48">
  <Image
    src="/photo.jpg"
    fill
    style={{ objectFit: 'cover' }}
    alt="Photo"
  />
</div>
For responsive with maintained ratio:
<Image
  src="/photo.jpg"
  width={1200}
  height={800}
  style={{ width: '100%', height: 'auto' }}
  alt="Photo"
/>

Verify the Fix

  1. Visual check - Images should look natural, not stretched or squished
  2. Re-run Lighthouse - "Displays images with correct aspect ratio" should pass
  3. Console check:
document.querySelectorAll('img').forEach((img) => {
  const style = getComputedStyle(img)
  if (style.objectFit !== 'fill')
    return // Using cover/contain is fine

  const naturalRatio = img.naturalWidth / img.naturalHeight
  const displayedRatio = img.clientWidth / img.clientHeight
  if (Math.abs(naturalRatio - displayedRatio) > 0.05) {
    console.warn('Still distorted:', img.src)
  }
})

Common Mistakes

  • Setting only width - width: 100% without height: auto can cause stretching if there's an inherited height.
  • Forgetting object-fit on avatars - Circle avatars with square images need object-fit: cover or they'll oval.
  • Wrong width/height attributes - If your HTML says 400x300 but the image is 1200x800, browsers use the attributes for ratio calculation. Make them match.
  • Background images - This audit only checks <img> elements. Distorted background images need background-size: cover or contain.

Test Your Entire Site

Your homepage might look perfect while product pages stretch images into a grid. Unlighthouse checks every page and surfaces all distorted images across your entire site.