I had a little situation the other day where I needed to make one of those aspect-ratio friendly boxes. This isn’t particularly new stuff. I think the original credit goes as far back as 2009 and Thierry Koblentz’s Intrinsic Ratios and maintained popularity even for other kinds of content with articles like Uncle Dave’s Ol’ Padded Box.
Let’s go on a little journey through this concept, as there is plenty to talk about.
The Core Concept: padding in percentages is based on width
Even when that is a little unintuitive, like for vertical padding. This isn’t a hack, but it is weird: padding-top and padding-bottom is based on the parent element’s width. So if you had an element that is 500px wide, and padding-top of 100%, the padding-top would be 500px.
Isn’t that a perfect square, 500px × 500px? Yes, it is! An aspect ratio!
If we force the height of the element to zero (height: 0;) and don’t have any borders. Then padding will be the only part of the box model affecting the height, and we’ll have our square.
Now imagine instead of 100% top padding, we used 56.25%. That happens to be a perfect 16:9 ratio! (9 / 16 = 0.5625).
Now we have a friendly aspect ratio box, that works well in fluid width environments. If the width changes, so does the height, and the element keeps that aspect ratio.
Use case: a background-image
Perhaps we’ve made a typographic lockup. It’s for the title of an article, so it makes sense to use an

tag.

Happy Birthday

We can make that

tag the aspect ratio box and apply the lockup as a background image.
h1 {
overflow: hidden;
height: 0;
padding-top: 56.25%;
background: url(/images/happy-birthday.svg);
}
But I lied about that aspect ratio up there. It’s not actually a 16:9 image. I just downloaded that graphic off a stock photography site. It happens to be an SVG with a viewBox=0 0 1127.34 591.44 which means it’s essentially an 1127.34 × 591.44 image in terms of aspect ratio. Or it could have been a 328 × 791 image.
I’d say it’s very common for any random image not to fit into a very specific pre-defined aspect ratio…
The Math of Any Possible Aspect Ratio
Perfect squares and 16:9 stuff is great, but the values used for those are just simple math. An aspect ratio can be anything, and they commonly are completely arbitrary. A video or image can be cropped to any size.
So how do we figure out the padding-top for our 1127.34 × 591.44 SVG above?
One way is using calc(), like this:
padding-top: calc(591.44 / 1127.34 * 100%);
It was expressed to me not long ago that using calc() here may be “slower”, but I’ve never seen any evidence of that. I imagine that yes, the computer does need to calculate something, so in a head-to-head battle against a situation where it doesn’t, calculating is slower. But a math problem doesn’t seem like too much work for a computer. For example, the popular Intel Pentium III (released in 1999) could do 2,054 MIPS or “Millions of instructions per second”, so it would make imperceptively quick work of a division problem. And now chips are 50× faster.
If we were using a preprocessor like Sass, we could do the calculation ahead of time:
padding-top: 591.44px / 1127.34px * 100%;
Either way, I’m a fan of leaving the math in the authored code.
How do you put content inside if padding is pushing everything down?
We hid the content in the demo above, by letting the content get pushed out and hiding the overflow. But what if you need an aspect ratio box while keeping content inside of it? That’s slightly trickier. We’ll need to position it back up into place. Absolute positioning can be up for that job.
Say we’re just using text alone now, but still want the aspect ratio box. We’ll need an inside wrapper for the absolute positioning. Let’s get specific with our classnames:

Happy Birthday

Then do the positioning:
.aspect-ratio-box {
height: 0;
overflow: hidden;
padding-top: 591.44px / 1127.34px * 100%;
background: white;
position: relative;
}
.aspect-ratio-box-inside {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Just for fun, let’s go full blast here and center that text and size it so it scales with the box:

Happy Birthday

Few more classes to style:
.flexbox-centering {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.viewport-sizing {
font-size: 5vw;
}
Use Case: Video
This is probably the #1 most common and practical use case for all this aspect ratio box stuff. HTML5