How to keep an image at its aspect ratio in HTML

Set one dimension and let the other be auto. Squashed images almost always come from setting both, and the fix is one line.

To keep an image at its aspect ratio in HTML, dictate one dimension and let the browser work out the other:

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

That single rule fixes most stretched images on most pages. The browser now scales the height to match whatever width the image ends up with.

The same photograph twice: fixed width and height above, the same width with height auto below.
The same photograph twice: fixed width and height above, the same width with height auto below.

Why images stretch

An image has its own proportions. Fix both dimensions in a way that disagrees with them and the browser does what you said, distorting the picture.

/* forces a 4:3 photo into a square */
img { width: 300px; height: 300px; }

The same happens with a stray inline style, or a global rule such as img { height: 200px } written for one component and inherited by another.

When something looks squashed, search for a second dimension before anything else. It is almost always there.

Fixed box, correct proportions

Sometimes the layout genuinely requires a fixed box. Cards in a grid look wrong when every image is a different height.

object-fit resolves it. The element keeps the size you set and the picture inside is scaled and cropped rather than squashed:

.card img {
  width: 100%;
  height: 220px;
  object-fit: cover;
  object-position: center;
  display: block;
}
Value Result
fill Stretches to the box. The default, and the cause of most distortion
cover Fills the box, crops the overflow, proportions intact
contain Fits entirely inside, leaves empty space at two edges
scale-down Like contain, but never enlarges a small image
none Original size, cropped by the box

Use cover for photographs, where losing an edge is acceptable. Use contain for logos, diagrams and screenshots, where cropping loses meaning.

object-position moves the crop. center top is worth setting on portraits, since a centred crop often takes the chin and leaves out the forehead.

Two cards of identical size: one with object-fit cover, one with contain and visible empty space.
Two cards of identical size: one with object-fit cover, one with contain and visible empty space.

Reserving space before the file arrives

Put the real pixel dimensions on the tag:

<img src="chart.png" alt="Revenue by quarter" width="1200" height="675">

Browsers read the pair as a ratio and hold the right amount of space while the file downloads. Without it the page reflows as each image lands, and the reader loses their place mid-sentence.

The attributes do not conflict with responsive CSS, as long as you keep height: auto:

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

Omit height: auto and the attribute wins, which reintroduces the stretch you were avoiding.

When the dimensions vary

For images whose size you do not know in advance, put the ratio on the container:

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

The container holds its shape whatever arrives, and the image fills it without distortion. This is the pattern for user uploads and for lists built from a spreadsheet.

aspect-ratio works on the image itself too, which is useful when a picture must be cropped to a specific shape regardless of what it is:

.square img { aspect-ratio: 1 / 1; width: 100%; object-fit: cover; }

A checklist for keeping an image at its aspect ratio

  1. Is a second dimension set anywhere, including inline styles and inherited rules?
  2. Is height: auto present next to max-width: 100%?
  3. Does the box have to be fixed? If so, is object-fit set?
  4. Are the real width and height attributes on the tag?
  5. Is display: block set, to remove the baseline gap under the image?

That last one is cosmetic rather than proportional, but it explains the few stray pixels under images inside coloured containers.

A page loading with the image space already reserved. Text below does not shift as the file arrives.
A page loading with the image space already reserved. Text below does not shift as the file arrives.

Padding counting twice. A box with padding and a percentage width can exceed its column unless box-sizing: border-box is set. Box sizing covers it.

Images that never arrive. A perfectly proportioned image still shows nothing if the path does not travel with the file. Images not showing in HTML lists the causes, and embedding images as base64 is one way to prevent it.

Different sizes for different screens. When one file is wrong at both ends, making an image responsive covers srcset and sizes.

Checking it on a real screen

Proportion problems show up at widths you are not looking at. Resize the window to phone width and back before calling it done.

Paste the HTML into a NOS document and it renders as written, images and CSS included, at an address you can open on your own phone. That is a more honest test than a narrow desktop window.

The address does not change when you adjust the rules, so you can fix the ratio and reload the same link. Turning HTML into a link is that step, and the HTML editor online shows the effect of each object-fit value as you type it.

Ratios worth knowing

Picking a ratio deliberately beats accepting whatever the camera produced, especially in a grid where the shapes have to agree.

Ratio Where it fits
16 / 9 Video frames, wide banners, screen recordings
4 / 3 Ordinary photographs and most screenshots
3 / 2 Camera output, article headers
1 / 1 Avatars, product tiles, anything in a dense grid
1 / 1.414 A4, for anything page-shaped

Write them as two numbers with a slash rather than a decimal. 16 / 9 is readable six months later; 1.7778 is not.

One practical rule for grids. Choose the ratio from the content that would suffer most from cropping, then let the rest of the set adapt to it. Doing the reverse produces a tidy grid with a headless portrait in it.

A grid of cards using a single one-to-one ratio, with images of different original shapes cropped to fit.
A grid of cards using a single one-to-one ratio, with images of different original shapes cropped to fit.

Questions people ask

Why is my image stretched?

Because both width and height are fixed and they do not match the proportions of the file. The browser obeys you literally. Set height to auto, or width to auto, so only one dimension is dictated and the other follows.

How do I fill a fixed box without distorting the picture?

Keep the fixed width and height on the element and add object-fit cover. The image scales until it fills the box and the overflow is cropped. Proportions stay correct and the box stays the size you wanted.

Should I still put width and height attributes on the img tag?

Yes. Modern browsers read them as a ratio and reserve the correct space before the file arrives, which stops the page jumping as images load. Pair them with height auto in CSS so they do not force a literal size.

What is the difference between object-fit cover and contain?

Cover fills the box and crops whatever does not fit. Contain fits the whole image inside the box and leaves empty space at two edges. Use cover for photographs and contain for logos and diagrams you must not crop.

Keep reading