CSS aspect-ratio is a property that gives a box a preferred width-to-height ratio, written as a ratio such as 16 / 9, so the browser can compute one side from the other. It is defined in CSS Box Sizing Module Level 4 and has been available in all browsers since September 2021, per MDN. The initial value is auto, which uses the intrinsic ratio of images and video and gives other boxes no ratio.
The ratio is width divided by height. aspect-ratio: 16 / 9 means the width is 16 parts for every 9 parts of height, and a plain number such as 1 or 0.5 is also accepted. A ratio only acts when at least one size is auto. If both width and height are set, the ratio has no effect.
Chromium 153 measured these boxes, all in a 400px wide container unless a width is shown:
#a { aspect-ratio: 16 / 9; } /* width auto */
#b { aspect-ratio: 16 / 9; height: 100px; } /* height set */
#c { aspect-ratio: 1; width: 100px; height: 300px; } /* both set */
#f { aspect-ratio: 3 / 2; width: 150px; padding: 10px; box-sizing: content-box; }
#g { aspect-ratio: 3 / 2; width: 150px; padding: 10px; box-sizing: border-box; }
a 400 x 225
b 177.765625 x 100
c 100 x 300
f 170 x 120
g 150 x 100
Box a fills the container and derives 225 from 400 x 9 / 16. Box b has a set height, so the width is derived instead and no longer fills the row. In c both sizes are set, so the ratio is ignored. In f the 3 / 2 ratio applies to the 150 by 100 content box, and padding adds 20 to each side.
Set aspect-ratio: 16 / 9 and width: 100% on the wrapper, with no height. The wrapper keeps a 16 by 9 shape at any width, replacing the older padding-top: 56.25% hack. For an img, an iframe or a video, also add width and height attributes to the element, so the browser can reserve space before the file loads.
An element with a preferred ratio has an automatic minimum size, so its content can push it past the ratio. In the same run, a 100px wide box with aspect-ratio 1 and sixteen words of text grew taller than 100px (the exact height depends on the font). Adding overflow: hidden made it 100 x 100, because a scroll container gets no content-based minimum. You can also set min-height: 0.