aspect-ratio: replacing the padding hack
One property to enforce proportional dimensions. No more padding-top percentages, no more wrapper divs.
The old padding hack
Before aspect-ratio, the only way to maintain proportions was to exploit the fact that padding-top percentages are relative to the element's width. A 16:9 container required padding-top: 56.25% with a positioned child. It worked, but it was fragile and unintuitive.
/* The old way — don't do this anymore */
.video-wrapper {
position: relative;
padding-top: 56.25%; /* 9 / 16 = 0.5625 */
}
.video-wrapper > iframe {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
}
The modern syntax
The aspect-ratio property accepts a ratio as width / height. The element's height is automatically computed from its width:
.video-wrapper {
aspect-ratio: 16 / 9;
inline-size: 100%;
}
.square-avatar {
aspect-ratio: 1; /* shorthand for 1 / 1 */
inline-size: 3rem;
border-radius: 50%;
}
.golden-card {
aspect-ratio: 1.618 / 1; /* golden ratio */
}
width and height are set explicitly, aspect-ratio is ignored. It only applies when at least one dimension is auto.Images and object-fit
Images have a natural aspect ratio from their file dimensions. Setting aspect-ratio on an image overrides that natural ratio. Combine it with object-fit to control how the image fills the box:
.thumbnail {
aspect-ratio: 4 / 3;
inline-size: 100%;
object-fit: cover; /* crops to fill */
object-position: center;
border-radius: 0.5rem;
}
.contain-img {
aspect-ratio: 16 / 9;
object-fit: contain; /* letterboxes to fit */
background: oklch(0.2 0 0);
}
Responsive media containers
For embedded media like iframes and videos, aspect-ratio on the container eliminates layout shift before the content loads:
.embed {
aspect-ratio: 16 / 9;
inline-size: 100%;
background: oklch(0.15 0 0);
border-radius: 0.75rem;
overflow: hidden;
}
.embed > iframe {
inline-size: 100%;
block-size: 100%;
border: none;
}
This also works beautifully with content-visibility: auto — the browser knows the exact dimensions even before rendering the content.
Constraints with min and max
The aspect-ratio property respects min-height and max-height. If content exceeds the ratio-computed height, the element grows to contain it by default:
.card {
aspect-ratio: 3 / 4;
min-block-size: 200px;
max-block-size: 600px;
}
/* Prevent overflow — clip to the ratio */
.strict-ratio {
aspect-ratio: 1;
overflow: hidden;
}
overflow: hidden if you need the ratio to be strict.Grid and aspect-ratio
Combine aspect-ratio with CSS Grid for uniform card layouts where each item maintains the same proportions regardless of content length:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.gallery > img {
aspect-ratio: 1;
inline-size: 100%;
object-fit: cover;
border-radius: 0.25rem;
}