w3tweaks.com · CSS Tutorial

CSS aspect-ratio

Eliminate layout shift. Responsive videos. Perfect image grids. One property.

Tab 1

Ratio Explorer — Click Any Ratio or Enter Custom

See how the element responds to the aspect-ratio value. The element width stays at 100% — only the height is computed from the ratio.

/
Preview 16 / 9
/* Only width is set — height auto-computed */
.element {
  width: 100%;
  aspect-ratio: 16 / 9;
}
Common Ratios Reference
CSS valueDecimalUse case
16 / 91.78HD video, YouTube, most hero images
4 / 31.33Old TV, presentation slides, product images
1 / 11.00Instagram square, avatar, icon containers
3 / 21.50Photography standard (35mm), blog cards
2 / 12.00Twitter cards, wide banner ads
1.91 / 11.91Open Graph (og:image), Facebook link preview
9 / 160.56TikTok, Instagram Reels, vertical video
4 / 50.80Instagram portrait, tall product photo
21 / 92.33Ultrawide cinematic, panoramic hero
The key rule: aspect-ratio only works when at least one dimension is auto. Set width: 100% and leave height unset — the browser calculates height from the ratio. Set both width and height explicitly and aspect-ratio is silently ignored.
Tab 2

Real Patterns — The Ones You'll Actually Use

Click the CLS demo to simulate page load with and without aspect-ratio and see the layout shift in action.

🎬 Responsive Video / iFrame Embed
/* Modern — no wrapper div needed */
iframe {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: none;
}

Replaces the old padding-bottom: 56.25% wrapper hack. The iframe itself holds the ratio — no extra div needed.

🖼️ Consistent Image Grid
🌅
🏔️
🌊
🌿
🌆
🌌
.gallery-item {
  aspect-ratio: 1 / 1;
  overflow: hidden;
}
.gallery-item img { object-fit: cover; }

Every image cell stays square regardless of the image's natural proportions. object-fit: cover fills the space without distortion.

👤 Always-Round Avatars
😊
64px
🎯
48px
🔥
36px
24px
.avatar {
  aspect-ratio: 1; /* same as 1/1 */
  border-radius: 50%;
  overflow: hidden;
}

aspect-ratio: 1 (no slash) is the shorthand for a perfect square. No need to set both width and height — height always matches width.

📊 CLS Demonstration — Click to Simulate Load
Without aspect-ratio
Article text above the image...
Image loads here after delay
This text JUMPS down when the image loads ↑
With aspect-ratio ✓
Article text above the image...
Space reserved — no jump ✓
This text stays in place ✓

The top example's text jumps when the image loads (CLS). The bottom reserves space with aspect-ratio: 16/9 — zero layout shift.

🔄 Old Padding Hack vs Modern
Old hack
padding-bottom: 56.25%
Modern ✓
aspect-ratio: 16/9
/* Old — complex, fragile */
.wrap { position: relative; padding-bottom: 56.25%; }
.inner { position: absolute; inset: 0; }

/* Modern — one line */
iframe { width: 100%; aspect-ratio: 16 / 9; }

The padding hack needed 3 elements and 5 CSS rules. aspect-ratio needs 1 CSS rule. Safe for production since Chrome 88, Firefox 89, Safari 15 — 2021.

🔮 auto 16/9 — The CLS Image Fix
/* Most important pattern for images */
img {
  width: 100%;
  height: auto;
  aspect-ratio: auto 16 / 9;
  /* ↑ uses intrinsic ratio when loaded */
  /* ↑ fallback while loading */
}

The auto keyword tells the browser to use the image's intrinsic ratio when it's loaded. The 16/9 after it is the fallback while the image is still loading — reserving exactly the right space to prevent CLS.

Best practice for all images: Always add width and height HTML attributes to <img> tags. The browser uses these to calculate aspect-ratio: auto before the image loads, giving zero CLS with no CSS needed.
Tab 3

Edge Cases & Gotchas

The tricky situations where aspect-ratio surprises you — and how to fix them.

Gotcha 1: Both dimensions set = ratio ignored

When both width and height are explicitly set, aspect-ratio has no effect. At least one must be auto.

❌ Ratio ignored
80×40
✅ Ratio applied
square
/* ❌ aspect-ratio is silently ignored */
.box { width: 80px; height: 40px; aspect-ratio: 1; }
/* ✅ height auto → ratio applies */
.box { width: 80px; aspect-ratio: 1; }
Gotcha 2: Content overflows → ratio breaks

Long content inside an aspect-ratio box expands the box height beyond the ratio. Fix with min-height: 0; overflow: hidden.

Without fix
This long content overflows and breaks the 2:1 ratio by pushing the height beyond what it should be at this width
With fix ✓
Long content is clipped by overflow:hidden — ratio maintained ✓
.ratio-box {
  aspect-ratio: 2 / 1;
  min-height: 0; /* prevent expansion */
  overflow: hidden; /* clip excess */
}
Gotcha 3: Flexbox stretch overrides ratio

In a flex container, align-items: stretch (default) can force height and override the ratio. Fix with align-self: flex-start or align-items: flex-start.

1
2
3
.flex-parent {
  display: flex;
  align-items: flex-start; ← fix
}
.item { aspect-ratio: 1; min-height: 0; }
Grid: Works perfectly out of the box

In CSS Grid, aspect-ratio works naturally — items get their width from the grid track and height is computed from the ratio.

1
2
3
.grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.item { aspect-ratio: 1; overflow: hidden; }

Add overflow: hidden on grid items to prevent content from pushing beyond the ratio. No min-height: 0 needed in most grid cases.

@supports — Graceful Fallback

For the rare case of supporting browsers before 2021, use @supports to progressively enhance:

/* Base: old padding hack */
.video-wrap { position: relative; padding-bottom: 56.25%; }
.video-wrap iframe { position: absolute; inset: 0; }

/* Enhanced: modern aspect-ratio */
@supports (aspect-ratio: 16 / 9) {
  .video-wrap { padding-bottom: unset; }
  .video-wrap iframe { position: static; width: 100%; aspect-ratio: 16/9; }
}

In practice: aspect-ratio is supported in Chrome 88+, Firefox 89+, Safari 15+ — released in 2021. Global coverage is 97%+ in 2026. The fallback is only needed for very old devices.

Read the tutorial