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.
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.
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)
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.
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).