skip to content

How would you use the CSS aspect-ratio property to reserve space for a media embed, and in which cases is the declared ratio ignored?

level: seniorimportance: should knowfreq 50%

answer

  1. fills in the axis you left auto
  2. computable before the bytes arrive
  3. two definite sizes, no ratio applied
  4. content can outgrow the shape
  5. stretch alignment quietly defeats it

basics

~20 s

Declare aspect-ratio on the box and leave one axis auto: aspect-ratio: 16 / 9 with a fluid width computes the height before any content loads, holding the space open. The ratio is ignored when both width and height are definite, and the box can still grow past it when content does not fit.

solid answer

~50 s

The pattern is `aspect-ratio: 16 / 9` on the wrapper or the embed itself, with `width: 100%` and the block size left to `auto`. The height is then computed from the definite width, so the space is reserved at layout time rather than when the media arrives — that is what prevents the page from jolting. The ratio only fills in an **auto** dimension: give the box both a definite `width` and a definite `height` and the ratio is ignored entirely. It also yields to content — a box with a preferred ratio takes a content-based automatic minimum size in the ratio-dependent axis, so a too-tall child makes the box grow rather than overflow; `min-height: 0` restores hard overflow. For an `iframe` embed you normally pair it with `width: 100%; height: 100%` inside a ratio'd wrapper, and for images with `object-fit: cover` so a mismatched source is cropped rather than stretched.

code

css · 16 lines
css
.embed {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.embed > iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.card-media {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

go deeper

for a junior

Know the syntax aspect-ratio: 16 / 9 and that you set only one dimension and let the other stay auto. Recognise it as the modern replacement for the percentage-padding ratio box.

for a middle

Explain that the ratio only fills an auto dimension, so declaring both width and height ignores it entirely, and that the ratio is derived against the definite axis before any resource has loaded.

for a senior

Demonstrate the production details: reserving space so the page does not shift, pairing with object-fit for off-ratio sources, and knowing that content-based minimums and stretch alignment in flex or grid can silently defeat the ratio.

for a principal

Own the policy: every media slot in the system declares a ratio so layout stability is structural rather than per-page, and be explicit about which ratios the design language supports and how off-ratio assets are cropped.

## What the property does `aspect-ratio` gives a box a **preferred aspect ratio**: a relationship between its inline and block sizes that the layout algorithm uses to fill in whichever one is `auto`. ```css .video-frame { width: 100%; aspect-ratio: 16 / 9; /* height computed from width */ } ``` The value is `<number>` or `<ratio>` (`1`, `16 / 9`, `4/3`), optionally prefixed with `auto` as in `aspect-ratio: auto 16 / 9`, which means "use the element's natural ratio if it has one, otherwise fall back to 16/9". That `auto` form matters only for replaced elements, which are the only boxes with a natural ratio of their own. It has been widely supported since 2021 (Chrome 88, Firefox 89, Safari 15), which is why the older `padding-top: 56.25%` ratio-box hack — exploiting the fact that percentage padding resolves against the *inline* size in both axes — is now legacy rather than current practice. ## Reserving space The reason this is an interview question is layout stability. If a slot for a video, a hero image or a map has no height until the resource loads, everything below it moves when it arrives. A ratio breaks that dependency: the inline size is definite from the containing block, so the block size is computable immediately, with nothing loaded. ```css .embed { width: 100%; aspect-ratio: 16 / 9; } .embed > iframe { width: 100%; height: 100%; border: 0; } ``` An `iframe` has no intrinsic ratio, so the wrapper supplies one and the frame fills it. For an `img`, the intrinsic ratio usually already does the job — but a declared `aspect-ratio` is useful when you want a *uniform* slot regardless of the source, in which case pair it with `object-fit: cover` so an off-ratio source is cropped rather than squashed: ```css .card-media { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; } ``` ## When the ratio is ignored **Both axes definite.** The ratio only ever computes an `auto` dimension. Declare `width: 400px; height: 300px; aspect-ratio: 16 / 9` and you get a 400x300 box; the ratio contributes nothing. This is the single most common surprise, usually caused by a `height` inherited from a shared class or a UA stylesheet rather than one the author remembers writing. **Neither axis definite in a context that will not give one.** If the box's inline size is itself content-based, the ratio has no definite input to work from and the result is whatever the content produces. **Content that does not fit.** For a box with a preferred aspect ratio, the automatic minimum size in the ratio-dependent axis is *content-based*, not zero. So a ratio'd box containing more text than the ratio allows grows taller instead of overflowing: ```css .tile { aspect-ratio: 1 / 1; } /* square until the text is too long */ .tile { aspect-ratio: 1 / 1; min-height: 0; } /* stays square, content overflows */ ``` This behaviour is usually what you want — silently clipped text is worse than a stretched tile — but it does mean `aspect-ratio` is a preference, not a guarantee. **Explicit min/max constraints.** The min/max clamps run after the ratio-derived size, so `aspect-ratio: 16 / 9; max-height: 300px` yields a box capped at 300px whose actual ratio is no longer 16:9. ## Interactions worth naming - As a **flex item**, a ratio'd box in a row container gets its inline size from flex sizing, then derives its block size from the ratio; `align-items: stretch` (the default) can override the block size, so set `align-self: start` or an explicit alignment when you need the ratio honoured. - As a **grid item**, stretching in both axes is the default and will defeat the ratio for the same reason; `place-self: start` restores it. - For **replaced elements**, `aspect-ratio` overrides the intrinsic ratio unless you use the `auto` prefix, which prefers the natural one. ## What a strong answer includes The pattern, the reason it stabilises layout (block size computable before load), the both-definite ignore rule, the content-based minimum that lets a box outgrow its ratio, and the pairing with `object-fit` for images. Mentioning that alignment defaults in flex and grid can silently defeat the ratio is what marks real production experience.

  • Why does a box with aspect-ratio: 1 / 1 sometimes end up taller than it is wide?
    Because a box with a preferred aspect ratio takes a *content-based* automatic minimum size in the ratio-dependent axis. If the content needs more block size than the ratio allows, the box grows rather than overflowing — the ratio is a preference, not a hard constraint. Set `min-height: 0` (or `min-block-size: 0`) to reinstate a zero floor and let the content overflow the square instead.
  • What did people use before aspect-ratio, and why did that hack work?
    The padding-box trick: an empty wrapper with `padding-top: 56.25%` and an absolutely positioned child filling it. It worked because percentage padding — vertical included — resolves against the containing block's *inline* size, so the padding produced a height proportional to the width. `aspect-ratio` (widely supported since 2021) expresses the same intent directly, without the positioning scaffolding.
  • You set aspect-ratio on a flex item and it comes out the wrong height. What is the likely cause?
    Default stretch alignment. In a row-direction flex container, `align-items: stretch` gives the item a definite cross size, and once both axes are definite the ratio is ignored. The fix is to stop the stretch — `align-self: start`, `center`, or `end` on the item — so the block size is left auto and can be derived from the ratio. Grid items behave the same way, resolved with `place-self`.

A declared ratio is like telling a picture framer the shape but only one measurement — useful right up until you also hand them the second measurement, at which point the shape is no longer their decision.

saying these in an interview costs you the question

  • Thinks aspect-ratio overrides an explicitly declared height
  • Believes a ratio'd box can never be outgrown by its content
  • Says aspect-ratio prevents image distortion without object-fit
  • Claims the property still needs a vendor prefix
  • Assumes an iframe has an intrinsic ratio of its own

context