{"id":255404,"date":"2017-06-08T08:47:49","date_gmt":"2017-06-08T15:47:49","guid":{"rendered":"http:\/\/css-tricks.com\/?p=255404"},"modified":"2021-03-09T15:47:17","modified_gmt":"2021-03-09T23:47:17","slug":"aspect-ratio-boxes","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/aspect-ratio-boxes\/","title":{"rendered":"Aspect Ratio Boxes"},"content":{"rendered":"\n

I had a little situation the other day where I needed to make one of those aspect-ratio friendly boxes<\/strong>. This isn’t particularly new stuff. I think the original credit goes as far back as 2009 and Thierry Koblentz’s Intrinsic Ratios<\/a> and maintained popularity even for other kinds of content with articles like Uncle Dave’s Ol’ Padded Box<\/a>.<\/p>\n\n\n\n

Let’s go on a little journey through this concept, as there is plenty to talk about.<\/p>\n\n\n\n\n\n\n

The Core Concept: padding in percentages is based on width<\/h3>\n\n\n

Even when that is a little unintuitive, like for vertical padding. This isn’t a hack, but it is weird: padding-top<\/code> and padding-bottom<\/code> is based on the parent element’s width<\/code>. So if you had an element that is 500px wide, and padding-top<\/code> of 100%, the padding-top<\/code> would be 500px.<\/p>\n\n\n\n

Isn’t that a perfect square, 500px \u00d7 500px? Yes, it is! An aspect ratio!<\/p>\n\n\n\n

If we force the height of the element to zero (height: 0;<\/code>) 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.<\/p>\n\n\n\n

Now imagine instead of 100% top padding, we used 56.25%. That happens to be a perfect 16:9 ratio! (9 \/ 16 = 0.5625).<\/p>\n\n\n\n

Now we have a friendly aspect ratio box<\/a>, that works well in fluid width environments. If the width changes, so does the height, and the element keeps that aspect ratio.<\/p>\n\n\n\n

Use case: a background-image<\/h3>\n\n\n

Perhaps we’ve made a typographic lockup<\/a>. It’s for the title of an article, so it makes sense to use an <h1><\/code> tag.<\/p>\n\n\n\n

<h1>\n  Happy Birthday\n<\/h1><\/code><\/pre>\n\n\n\n

We can make that <h1><\/code> tag the aspect ratio box and apply the lockup as a background image.<\/p>\n\n\n\n

h1 {\n  overflow: hidden;\n  height: 0;\n  padding-top: 56.25%;\n  background: url(\/images\/happy-birthday.svg);\n}<\/code><\/pre>\n\n\n\n

The Math of Any Possible Aspect Ratio<\/h3>\n\n\n

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<\/em> completely arbitrary. A video or image can be cropped to any size.<\/p>\n\n\n\n

So how do we figure out the padding-top for our 1127.34 \u00d7 591.44 SVG above?<\/p>\n\n\n\n

One way is using calc()<\/code>, like this:<\/p>\n\n\n\n

padding-top: calc(591.44 \/ 1127.34 * 100%);<\/code><\/pre>\n\n\n\n

It was expressed to me not long ago that using calc()<\/code> 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\u00d7 faster.<\/p>\n\n\n\n

If we were using a preprocessor like Sass, we could do the calculation ahead of time:<\/p>\n\n\n\n

padding-top: 591.44px \/ 1127.34px * 100%;<\/code><\/pre>\n\n\n\n

Either way, I’m a fan of leaving the math in the authored code.<\/p>\n\n\n

How do you put content inside if padding is pushing everything down?<\/h3>\n\n\n

We hid<\/em> 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.<\/p>\n\n\n\n

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:<\/p>\n\n\n\n

<h1 class=\"aspect-ratio-box\">\n  <div class=\"aspect-ratio-box-inside\">\n    Happy Birthday\n  <\/div>\n<\/h1><\/code><\/pre>\n\n\n\n

Then do the positioning:<\/p>\n\n\n\n

.aspect-ratio-box {\n  height: 0;\n  overflow: hidden;\n  padding-top: 591.44px \/ 1127.34px * 100%;\n  background: white;\n  position: relative;\n}\n.aspect-ratio-box-inside {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}<\/code><\/pre>\n\n\n\n

Just for fun, let’s go full blast here and center that text and size it so it scales with the box:<\/p>\n\n\n\n

<h1 class=\"aspect-ratio-box\">\n  <div class=\"aspect-ratio-box-inside\">\n    <div class=\"flexbox-centering\">\n      <div class=\"viewport-sizing\">\n          Happy Birthday\n      <\/div>\n    <\/div>\n  <\/div>\n<\/h1><\/code><\/pre>\n\n\n\n

Few more classes to style:<\/p>\n\n\n\n

.flexbox-centering {\n  height: 100%;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n.viewport-sizing {\n  font-size: 5vw;\n}<\/code><\/pre>\n\n\n\n