aspect-ratio
property. This guide shows production patterns, accessibility tips, and a tiny fallback so your layout stays predictable and responsive—with fewer hacks and less layout shift (CLS).
Why aspect ratio matters in responsive design
Responsive layouts break when heights collapse or media crops unpredictably. Declaring a CSS aspect ratio guarantees the element’s height scales from its width—preventing layout jumps and keeping your design consistent across viewports.
Tip: for quick calculations or prototyping, try an Aspect Ratio Calculator to convert between sizes while preserving proportion.
The modern solution: aspect-ratio
.card {
aspect-ratio: 16 / 9; /* width / height */
width: 100%;
background: #f6f7f9;
border-radius: 12px;
}
- Squares:
aspect-ratio: 1 / 1
- Landscape cards/videos:
16 / 9
- Vertical previews:
9 / 16
Responsive images: cover vs contain (no CLS)
Use aspect-ratio
to reserve space, and object-fit
to control how the image fills that space. Also add width
and height
attributes to each <img>
to let the browser infer the ratio immediately and avoid CLS.
<div class="media media--16x9">
<img src="landscape.jpg" alt="Mountain lake at sunrise" width="1600" height="900" loading="lazy">
</div>
.media { aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden; }
.media > img {
width: 100%;
height: 100%;
object-fit: cover; /* crop excess to fill the box */
display: block;
}
Use object-fit: contain
for UI diagrams or charts where cropping is unacceptable (letterboxing may appear).
Responsive video & iframes (YouTube, Vimeo, maps)
Option A: Set ratio on the iframe
<iframe
class="video"
src="https://www.youtube.com/embed/VIDEO_ID"
title="Video title"
allowfullscreen
loading="lazy"></iframe>
.video {
aspect-ratio: 16 / 9;
width: 100%;
border: 0;
border-radius: 12px;
}
Option B: Wrapper pattern (handy for overlays)
<div class="video-wrap">
<iframe src="https://www.youtube.com/embed/VIDEO_ID" title="Video title" allowfullscreen loading="lazy"></iframe>
</div>
.video-wrap { aspect-ratio: 16 / 9; position: relative; }
.video-wrap > iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
CSS Grid galleries with consistent tiles
<ul class="grid">
<li class="tile"><img src="1.jpg" alt="Gallery item 1" width="1200" height="1200" loading="lazy"></li>
<li class="tile"><img src="2.jpg" alt="Gallery item 2" width="1200" height="1200" loading="lazy"></li>
<li class="tile"><img src="3.jpg" alt="Gallery item 3" width="1200" height="1200" loading="lazy"></li>
</ul>
.grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}
.tile {
aspect-ratio: 1 / 1; /* perfect squares */
border-radius: 12px; overflow: hidden; background: #eee;
}
.tile > img { width: 100%; height: 100%; object-fit: cover; display: block; }
Swap 1 / 1
for 3 / 4
, 2 / 3
, or 4 / 3
to change the gallery’s vibe.
Flexbox cards that keep their shape
.cards { display: flex; gap: 16px; flex-wrap: wrap; }
.card { flex: 1 1 260px; aspect-ratio: 4 / 3; border-radius: 14px; background: linear-gradient(#fafbfc, #f2f3f5); }
Dynamic aspect ratios with CSS variables
<div class="ratio" style="--w: 21; --h: 9;" aria-label="21 by 9 box"></div>
<div class="ratio" style="--w: 3; --h: 4;" aria-label="3 by 4 box"></div>
.ratio {
aspect-ratio: var(--w) / var(--h);
background: #f8fafc;
border: 1px dashed #d6dae1;
border-radius: 12px;
}
Cap hero height while preserving ratio
.hero {
aspect-ratio: 21 / 9;
width: 100%;
height: min(70vh, 680px); /* cap height on tall screens */
}
If you set both width and height explicitly, the element keeps that size; aspect-ratio
then acts as a preferred ratio during layout.
Fallback for older browsers
.ratio { aspect-ratio: 16 / 9; }
/* Only if aspect-ratio is not supported */
@supports not (aspect-ratio: 1 / 1) {
.ratio { position: relative; }
.ratio::before {
content: "";
display: block;
padding-top: calc(9 / 16 * 100%); /* height / width as percentage */
}
.ratio > * { position: absolute; inset: 0; }
}
Common pitfalls (and fixes)
- Mixing
min-height
withaspect-ratio
: prefermax-height
orheight: min(...)
. - Expecting
object-fit
to set the container ratio: it only controls how media fits inside. - Rounded corners not clipping images: add
overflow: hidden
to the container. - CLS from images: include
width
/height
attributes or putaspect-ratio
on the container. - Nested ratios collapsing: ensure the parent defines height via ratio before sizing children to
height: 100%
.
Copy-paste utility classes
/* Quick utilities */
.ratio-1x1 { aspect-ratio: 1 / 1; }
.ratio-4x3 { aspect-ratio: 4 / 3; }
.ratio-3x2 { aspect-ratio: 3 / 2; }
.ratio-16x9 { aspect-ratio: 16 / 9; }
.ratio-9x16 { aspect-ratio: 9 / 16; }
/* Media helpers */
.fit-cover { width: 100%; height: 100%; object-fit: cover; display: block; }
.fit-contain { width: 100%; height: 100%; object-fit: contain; display: block; }
.rounded-12 { border-radius: 12px; overflow: hidden; }
Common aspect ratios (and legacy padding)
Ratio | CSS | Legacy padding-top | Use case |
---|---|---|---|
1:1 | aspect-ratio: 1/1 |
100% | Avatars, square tiles |
4:3 | 4/3 |
75% | Classic photos, cards |
3:2 | 3/2 |
66.6667% | Editorial images |
16:9 | 16/9 |
56.25% | Video, hero banners |
9:16 | 9/16 |
177.7778% | Reels, vertical stories |
SEO & performance checklist
- Declare
aspect-ratio
on media wrappers and cards to reserve height. - On
<img>
, set accuratewidth
/height
attributes to cut CLS. - Use
loading="lazy"
for below-the-fold images/iframes. - Use descriptive
alt
text; never stuff keywords. - Add a progressive fallback via
@supports not (aspect-ratio: 1 / 1)
. - Cap extremes with
min()
/max()
/clamp()
to avoid overflow on unusual screens. - Test at multiple breakpoints and on low-end devices for jank.
FAQs
What is the simplest way to keep a video responsive?
Set aspect-ratio: 16/9
on the iframe (or wrapper) and width: 100%
, add loading="lazy"
and a descriptive title
for accessibility.
Should I use object-fit: cover
or contain
?
Use cover for thumbnails and hero images (cropping edges is fine). Use contain for UI/diagrams where everything must be visible.
Do I still need the padding-top hack?
Only for very old browsers. Provide it conditionally with @supports not (aspect-ratio: 1 / 1)
.
Can I limit hero height while keeping ratio?
Yes: height: min(70vh, 680px); aspect-ratio: 21/9;
caps height on tall screens while staying responsive.
Does aspect-ratio
work in Grid and Flex layouts?
Yes. The layout defines the width; the browser computes height from the ratio, keeping tiles consistent across rows.
Conclusion
For a truly CSS aspect ratio responsive layout, use the aspect-ratio
property wherever you previously relied on hacks—cards, media, tiles, and embeds. Combine it with object-fit
, set image dimensions to prevent CLS, and include a small fallback for legacy browsers. You’ll get cleaner code, smoother rendering, and a UI that scales beautifully across devices.