Maybe it’s just me, but I feel like a lot of the time learning new CSS features doesn’t involve just learning a what a single property does, more like getting to grips with a collection of properties and how they work together — even learning a whole specification. That’s certainly not a complaint from me: it makes sense to consider properties as part of an ecosystem. But I have to confess, I love it when a new CSS property lands in browsers that doesn’t have a steep learning curve and just works, with no fuss. The aspect-ratio property hits all the right spots there, neatly solving with a single line of CSS something that was, quite frankly, a bit of faff before. It’s been supported in browsers for going on a year now, but with Safari finally catching up in September 2021, we can finally feel confident using it with aplomb.

Goodbye, padding hack

In times gone by we needed to write some pretty ugly CSS to get elements to conform to an aspect ratio:

.aspect-box {
  position: relative;
}

.aspect-box::before {
  display: block;
  content: '';
  width: 100%;
  padding-bottom: calc(100% / (var(--aspect-ratio, 3 / 2)));
}

.aspect-box > :first-child {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

We tend to call this the “padding hack” because, well, that’s what it is. The custom property helps us cut down on repetition if we need more than one ratio. Here’s a rundown from CSS Tricks, and a demo here.

No one in their right mind wants to be writing all that. Ratio Buddy is a handy tool that generates the Sass snippet for you.

Practical usage of aspect-ratio

Using the CSS aspect-ratio property is far simpler: Specify width and height values for the aspect ratio, separated with a slash, or specify a single decimal value. These two aspect ratio values will have the same result:

.aspect-box {
  aspect-ratio: 3 / 2;
}

.aspect-box {
  aspect-ratio: 1.5;
}

You can explicitly set a width or height on the element and aspect-ratio will work pretty much as you might expect: Whichever dimension is unspecified will be automatically determined by the aspect ratio. If you set both the width and height to something other than auto, then the aspect ratio no longer applies. That’s not a bug, that’s deliberate and useful behaviour.

Height set

Width and height set (box no longer has aspect ratio)

Expand to fit

aspect-ratio is both intrinsically and extrinsically sized. That means it’s smart enough to respond to both content and context. Each of these three boxes has as aspect ratio of 2 / 1 and an explicit width set. The text content in the third box is longer than the available space, so rather than maintaining the aspect ratio, the element expands vertically to fit the content.

See the demo

If we set an explicit height instead, the element doesn’t expand, but instead we get overflow (which we could handle with the CSS overflow property if we choose to).

See the demo

Aspect ratio images with object-fit