CSS aspect-ratio
aspect-ratio is a CSS property that automatically computes an element's height from its width (or vice versa) using a fixed ratio.
Theory
TL;DR
- Like a photo frame that adjusts its height to match any width without distortion. You set the ratio, the browser does the math.
- Before 2021: developers used
padding-bottom: 56.25%hacks on wrapper divs. One property replaces all of that now. - Set one dimension (width or height) plus
aspect-ratio, and the browser solves for the other. - Skip it when both dimensions are already set explicitly.
Quick example
.video {
width: 100%;
max-width: 800px;
aspect-ratio: 16 / 9;
background: #000;
}
/* At 800px width: height is 450px. At 400px: height is 225px. */One property. No JavaScript. No padding tricks. The container stays 16:9 at any viewport size.
Why this replaced the padding hack
Before Chrome 88 (January 2021), percentage height had no reference point unless the parent had an explicit height. So developers used padding-bottom: 56.25% on a wrapper, because percentage padding always computes from width. A div with height: 0; padding-bottom: 56.25% gave you a 16:9 box, and the actual content sat inside via position: absolute.
It worked. But it was a hack. Extra markup, non-obvious CSS, confusing for anyone reading it later. In practice, I still see this pattern in codebases that started before 2021, often copy-pasted without anyone knowing a native solution exists.
aspect-ratio solves this directly. The browser computes used-height = used-width * (ratio-height / ratio-width) during the layout pass, after width is known. No wrappers. No padding tricks.
When to use
- Responsive video containers:
width: 100%+aspect-ratio: 16 / 9 - Image gallery thumbnails that scale with grid column width
- Product cards where the image area must keep its shape during resize
- Placeholder boxes before images load
Skip it when both width and height are set explicitly. The property is ignored in that case. Also skip it if Flexbox or Grid already controls the shape you want.
How the browser resolves it
Browsers (Blink, WebKit, Gecko) process aspect-ratio during the layout pass, after width is determined. For a block element with width: 100%, width is known first and height is computed from the ratio. In a vertical flex container where height is constrained, it works the opposite way. If both dimensions are explicit, the ratio is ignored entirely.
One edge case worth knowing: min-height and max-height can override the ratio-computed value. If the computed height from the ratio falls below min-height, the browser uses min-height and the ratio stops working as expected.
Common mistakes
Setting height alongside aspect-ratio in Flexbox:
/* Wrong - height overrides the ratio */
.flex-item {
flex: 1;
aspect-ratio: 16 / 9;
height: 100%;
}
/* Correct - remove height, let ratio set it */
.flex-item {
flex: 1;
aspect-ratio: 16 / 9;
}Assuming aspect-ratio: auto preserves image intrinsic ratio on all elements:
For replaced elements like img or video, auto does use the file's intrinsic ratio. But for regular div elements, auto defaults to 1:1. For images, width: 100%; height: auto; is usually the simpler and more predictable path.
Using it on table cells:
Table layout ignores aspect-ratio. The table sizing algorithm overrides it. Wrap the cell content in a div and apply the ratio there instead.
Parent collapses to zero in a float context:
If the parent has no height reference, the ratio cannot compute. Use Flexbox or Grid as the container layout, or give the parent an explicit height.
Real-world usage
- Tailwind CSS:
aspect-[16/9]utility in v3+ - Bootstrap 5.3+:
.ratioclass usesaspect-ratiowith a@supportsfallback for older browsers - Next.js / Vercel templates: video thumbnails and hero image containers
- react-player library: wraps iframes with
aspectRatioin inline styles instead of the old padding approach - Legacy browsers:
@supports not (aspect-ratio: 1) { padding-bottom: 56.25%; }for Safari before v15
Follow-up questions
Q: What happens if both width and height are set alongside aspect-ratio?
A: The ratio is ignored. Explicit dimensions always win. aspect-ratio only fills in the missing one.
Q: How does aspect-ratio: auto work on images?
A: For replaced elements (img, video), auto uses the file's intrinsic ratio. For regular elements it defaults to 1:1. For images, width: 100%; height: auto; is usually what you actually want.
Q: How do you support browsers before Chrome 88?
A: Use @supports not (aspect-ratio: 1) and provide the padding-bottom hack as a fallback. No separate polyfill needed, just progressive enhancement.
Q: In a CSS Grid, why does aspect-ratio sometimes get ignored on grid items?
A: Grid computes track sizes first. If a row track has an explicit height or the grid stretches items to fill the row, that height wins over the ratio. Fix: set align-items: start on the grid container, or apply the ratio to an inner div inside the grid item.
Q: Can you use CSS custom properties with aspect-ratio?
A: Yes. aspect-ratio: var(--ratio) works fine. Define --ratio: 16 / 9 in :root and reuse across components.
Examples
Responsive video embed
The classic use case. An iframe that stays 16:9 on any screen width, with no padding hack and no JavaScript.
<div class="video-wrapper">
<iframe
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
style="width: 100%; height: 100%; border: none;"
allowfullscreen>
</iframe>
</div>.video-wrapper {
width: 100%;
max-width: 800px;
aspect-ratio: 16 / 9;
margin: 0 auto;
overflow: hidden;
/* No position: absolute. No padding-bottom. Just works. */
}At 800px the height is 450px. At 400px it is 225px. The iframe fills the wrapper because its own width and height are 100% of the parent, and the parent's height comes entirely from the ratio.
Product image grid with consistent thumbnails
E-commerce listings need square thumbnails regardless of the original image dimensions. aspect-ratio locks the shape, object-fit handles the crop.
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.product-image {
width: 100%;
aspect-ratio: 1 / 1; /* always square */
overflow: hidden;
background: #f5f5f5;
border-radius: 4px;
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover; /* crop, not squish */
}object-fit: cover crops the image to fill the square without distortion. aspect-ratio: 1 / 1 guarantees the box stays square regardless of how wide the grid column gets.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.