loading...

How to implement only css responsive elements with a certain aspect ratio

albertodeago88 profile image Alberto De Agostini ・3 min read

If you just want the solution skip to the bottom of the article.

Why this tutorial

Some time ago I was developing a webapp when the design team manager comes by and tell me that there was a piece of the application that needed to maintain a 16:9 aspect ratio and be responsive, no matter the content inside.
Immediately I said "ok mate, not a problem", but after a while I was like "wait, how do I do that?".
I asked some colleagues and surprisingly I've found that noone already knew how to do it without using Javascript (I always try to avoid using js if possible, especially if I have to add some listener to scroll or resize).

As any developer would do I started searching on Google and yes I've found some answers but I've also found a lot of people asking for it and a lot of questions were not actually working or were not ideal.

That's why I'm writing this tutorial now, I hope it will be the simplest tutorial to understand how to do it.

Code it

We are going to need just 2 div, no matter the aspect ratio we want.
Time is up, let's code it, I'll explain later what's going on:

<div class="square">
  <div class="content">
    This is a square content
  </div>
</div>
.square {
  border: 2px dotted red;
  width: 250px;
  position: relative;
}
.square:after {
  content: "";
  display: block;
  padding-top: 100%;
}
.content {
  position: absolute;
  width: 100%;
  height: 100%;
}

We create a div square and inside we create another div with class content (class names obviously are arbitrary, those are just semantic to better explain what's the elements purpose).
In the css we add a border on the square just to see it easily and we set a width (the width value can be any value, if you want it to be responsive it will probably going to be 100%) and set the position to relative.
We also add an after pseudoelement to the square and add content property to make it visible, display to block to behave like a block and a padding-top of 100%. This padding-top is THE trick. By adding this property we are saying: "my element (square) is 250px width and has a padding-top (that count for div dimensions) of 100%, so 250px. The resulting square element will be 250 x 250 px.
This is also where the previous position relative enter the game: if we don't set it to relative and the content element position to absolute the result will be that any content will make the square element to grow in height, thus losing the aspect ratio.
Now to create a 16:9 element or any other aspect ratio just change the padding top this way:

.square:after {
  content: "";
  display: block;
  padding-top: calc(100% / (16/9));
}

this way it will be a 16:9 element (square class would be inappropriate then :D).

Playground/demo

I've created a simple Codepen with some easy examples where you can play and try it out by your own including a responsive one with 100% width. check it out.

Vue component

If you are a Vue enthusiast developer like me I've also created a component to handle this easily, check it out here vue-aspect-ratio

Conclusion

For my research this is the best way to address this issue, let me know if you have any questions or tips by commenting or feel free to reach me on my twitter.

Discussion

pic
Editor guide