Responsive images look squished when both width and height are fixed in CSS; the fix is max-width: 100% with height: auto so the image scales proportionally. If your responsive images look squished or stretched, you almost certainly set both a width and a height in CSS. An image has an intrinsic aspect ratio, and the moment you pin both dimensions to fixed values that do not match that ratio, the browser distorts the picture to obey you. The fix is one rule:
img {
max-width: 100%;
height: auto;
}max-width: 100% stops the image from overflowing its container (it shrinks to fit on small screens but never blows up past its natural size), and height: auto tells the browser to compute the height from the width so the aspect ratio is preserved. That is the whole job for the common case. The rest of this page is why it goes wrong, why you still want the HTML width and height attributes, and what to do when you genuinely need a fixed box.
Why the squish happens
The distortion comes from over-specifying. Any of these will do it:
/* Both fixed, ratio ignored: stretched */
img { width: 400px; height: 300px; }
/* Fluid width, fixed height: squished as the column narrows */
img { width: 100%; height: 200px; }In the first rule you forced a 4:3 box onto, say, a 16:9 photo, so the browser squashes the photo to fit. In the second, the width tracks the container while the height stays nailed at 200px, so the image gets more and more distorted as the viewport shrinks. A replaced element like <img> only keeps its proportions when at most one of its two dimensions is fixed and the other is left to follow.
So the rule is simple: set one dimension, let the other be auto. With responsive layouts the width is the one that flexes, so width (or max-width) is what you control and height: auto is what you hand back to the browser.
Keep the width and height HTML attributes anyway
Here is the part people get wrong: because they are setting height: auto in CSS, they assume they should strip the width and height attributes off the <img> tag. Do not. Those two things solve different problems and cooperate cleanly.
<img src="photo.jpg" width="1600" height="900" alt="...">The width and height attributes are the image's intrinsic size. The browser divides them to get the aspect ratio and reserves a correctly-shaped box before the file downloads. Without them, a width: 100%; height: auto image collapses to zero height until it loads, then shoves the page down when it arrives, which is exactly the layout shift that Cumulative Layout Shift (CLS) measures and Core Web Vitals penalises.
The CSS height: auto does not fight the attributes. The browser uses the attribute ratio to size the placeholder, then the responsive CSS scales the displayed image while holding that same ratio. Attributes for layout reservation, CSS for fluid display. You want both.
aspect-ratio: the modern reinforcement
If the markup cannot carry width/height attributes (a background-ish hero, a CMS that strips them, an element that is not an <img> at all), the aspect-ratio property reserves the box from CSS instead:
img {
max-width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}aspect-ratio: 16 / 9 tells the browser the shape ahead of time, so it can reserve space the same way the HTML attributes do. It is Baseline across current browsers, so you can lean on it in production. When the <img> already has matching width/height attributes, you do not need this too. It is the fallback for the cases where the attributes are not available.
When you DO need a fixed box: object-fit
Sometimes a fixed box is the design: a grid of thumbnails that must all be the same square, an avatar, a card header that has to be exactly 320 by 180 regardless of the source photo. There you do set both dimensions, and you stop the distortion with object-fit instead of height: auto:
.thumb {
width: 320px;
height: 180px;
object-fit: cover;
}object-fit controls how the image fills the box you forced on it, without stretching:
coverscales the image to fill the whole box and crops whatever overflows. Best for thumbnails and hero crops where edge loss is acceptable.containscales it to fit entirely inside the box, leaving letterbox or pillarbox bars. Best when the whole image must stay visible (logos, product shots).fillis the default, and it is the one that stretches. That is the behaviour you are escaping.
Pair it with object-position to choose which part survives the crop (object-position: center top keeps faces in frame). object-fit is Baseline and safe to use everywhere. The mental model: height: auto keeps the box matching the image; object-fit keeps the image matching the box.
Inside grid and flex containers
One more squish source worth naming: an <img> placed directly as a flex item can stretch along the cross axis because flex containers stretch items by default. If a sidebar image looks oddly tall, that is usually it. Keep the max-width: 100%; height: auto rule and let the image sit in a block wrapper, or set align-self: start on the item so the flex container stops stretching it.
For the wider picture of srcset, sizes, and serving the right file to each screen, see responsive images done properly. When the box dimensions come from a calculation rather than a literal value, CSS calc() is how you express them. And if you are styling images conditionally based on whether a wrapper has a caption or a particular class, the :has() parent selector makes that selection possible without JavaScript.
FAQ
You set both a fixed width and a fixed height in CSS (or width: 100% with a fixed height), and the ratio of that box does not match the image's natural ratio, so the browser distorts the image to fit. Set only one dimension and let the other be auto.
It tells the browser to calculate the height from whatever width the image ends up at, so the intrinsic aspect ratio is preserved. Combined with max-width: 100%, the image shrinks to fit narrow screens without ever stretching or overflowing.
Yes. The HTML width and height attributes give the browser the intrinsic ratio so it reserves a correctly-shaped box before the image loads, preventing layout shift (CLS). The CSS height: auto handles fluid display on top of that. They do not conflict; you want both.
Use aspect-ratio when the element cannot carry intrinsic width/height attributes (a non-img element, or markup a CMS strips). It reserves the box shape from CSS the same way the attributes would. If the img already has matching attributes, you do not need it as well.
Set both dimensions and add object-fit: cover (fills the box, crops the overflow) or object-fit: contain (fits inside, adds letterbox bars). The default, fill, is the one that stretches. Use object-position to control which part stays in frame when cropping.
See also
- Responsive images done properly: srcset, sizes, and serving the right file to each viewport.
- CSS calc() for real layouts: compute box dimensions instead of hard-coding them.
- The :has() parent selector: style images based on their wrapper or sibling context, no JavaScript.
Sources
Authoritative references this article was fact-checked against.
- object-fit, CSS reference (MDN)developer.mozilla.org
- aspect-ratio, CSS reference (MDN)developer.mozilla.org
- Aspect ratio mapping for images (MDN)developer.mozilla.org
- Optimize Cumulative Layout Shift (web.dev)web.dev
- Understanding and setting aspect ratios (MDN)developer.mozilla.org





