TL;DR: To maintain aspect ratio in CSS, use the native aspect-ratio property on boxes, images, and iframes. Pair images with HTML width/height to reserve space (prevent CLS), and use object-fit for cropping or containment. Add the classic padding-box fallback only for very old browsers.
What “maintain aspect ratio” means & why it matters
An aspect ratio is the width-to-height relationship of an element (e.g., 16/9, 4/3, 1/1). Preserving it prevents distortion, avoids layout shifts as media loads, and keeps responsive UIs consistent across devices—contributing to better UX and Core Web Vitals.
The modern solution: aspect-ratio
aspect-ratio gives the browser a preferred width:height ratio. It applies when at least one dimension is auto. If both width and height are fixed, the ratio won’t change the box.
/* Squares, rectangles, 16:9 frames */
.square { aspect-ratio: 1 / 1; }
.golden { aspect-ratio: 1.618 / 1; }
.video-frame { aspect-ratio: 16 / 9; width: 100%; }
- Quick rule: set
width(often100%) and let the browser calculateheightfrom your ratio. - Replaced elements: images/videos/iframes have intrinsic sizes; the intrinsic ratio wins unless you provide different sizing rules. You can still use
aspect-ratioto reserve space.
Images: intrinsic size, object-fit, and zero jank
For images, combine three best practices:
- Reserve space by setting HTML
widthandheightattributes that reflect the source image’s intrinsic dimensions (the browser derives the ratio from these values). - Optionally, add a CSS
aspect-ratioas an extra safeguard before the image loads. - Use
object-fitto control cropping (cover) or containment (contain), andobject-positionfor the focal point.
<img
class="thumb"
src="/images/cat.jpg"
alt="Cat on a windowsill"
width="1200" height="800">
.thumb {
width: 100%;
height: auto; /* uses the intrinsic ratio from width/height attrs */
aspect-ratio: 3 / 2; /* optional placeholder ratio */
object-fit: cover; /* or 'contain' if you never want cropping */
object-position: 50% 50%;
}
Bonus: Add responsive sources with srcset/sizes to serve the right image per viewport.
Responsive video & iframes (YouTube, Vimeo, maps)
The native property makes embeds painless—no wrappers or magic numbers.
<iframe class="yt" src="https://www.youtube.com/embed/VIDEO_ID" title="Video" allowfullscreen></iframe>
.yt {
width: 100%;
aspect-ratio: 16 / 9;
border: 0;
}
For vertically oriented content (e.g., shorts), switch to 9/16.
Cards & grids that always line up
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 1rem;
}
.card {
aspect-ratio: 4 / 3; /* consistent tile heights */
display: grid;
place-items: center;
padding: 1rem;
border-radius: 0.75rem;
}
Because each card has a set ratio, the grid remains tidy at any viewport size.
Advanced notes & edge cases
- When ratio seems ignored: If you set both
widthandheightto fixed values, the browser won’t useaspect-ratio. Leave one dimension asauto. - Viewport-based layouts: You can adapt UI by viewport ratio, e.g., show a sidebar only on wide screens.
/* Media queries using aspect ratio */
@media (min-aspect-ratio: 3/2) {
.sidebar { display: block; }
}
/* Range syntax is supported in many modern browsers */
@media (aspect-ratio > 3 / 2) {
.sidebar { display: block; }
}
Legacy fallback: the padding-box technique
For very old browsers, use a percentage padding to simulate height (percentage is based on the element’s width). Prefer the native property today.
<div class="ratio-16x9">
<div class="ratio-content">...content/iframe...</div>
</div>
.ratio-16x9 { position: relative; padding-top: 56.25%; } /* 9/16 */
.ratio-content { position: absolute; inset: 0; }
Common mistakes (and quick fixes)
- Both dimensions fixed. Fix: keep either width or height as
auto. - Unwanted cropping. Fix: use
object-fit: containor set a different focal point withobject-position. - Layout shift on image load. Fix: set HTML
width/heightto expose intrinsic ratio (and includeloading="lazy"judiciously). - Overusing wrappers and hacks. Fix: use native
aspect-ratiofirst; add the padding-box fallback only if necessary.
Copy-paste snippets
Square avatars (center-cropped)
.avatar { aspect-ratio: 1 / 1; width: 96px; border-radius: 50%; object-fit: cover; }
Responsive video/iframe
iframe, video { width: 100%; aspect-ratio: 16 / 9; }
Product image tiles (no cropping)
.product-img { aspect-ratio: 4 / 3; width: 100%; object-fit: contain; background: #f7f7f8; }
Responsive squares in a CSS Grid
.square-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: .75rem; }
.square-grid > * { aspect-ratio: 1 / 1; }
FAQ: CSS & aspect ratios
How do I maintain aspect ratio in CSS?
Use aspect-ratio (e.g., 16/9) with one dimension left auto. For media, also include HTML width/height to reserve space.
Does aspect-ratio work if both width and height are set?
No. The property is ignored if both dimensions are fixed. Keep one dimension auto.
What about images that crop badly?
Switch to object-fit: contain to avoid cropping, or use object-position to control the focal point when using cover.
Do I still need the padding-box hack?
Only if you must support very old browsers. Otherwise, the native property is clearer, faster, and less error-prone.
Pre-publish checklist
- Use
aspect-ratiofor boxes, embeds, and placeholders. - Add HTML
width/heighton images to prevent CLS. - Pick the right fit mode:
covervscontain. - Test key breakpoints and landscape vs portrait viewports.
- Verify in Lighthouse/PageSpeed that CLS is stable and images are responsive.