When I give an image a percent width or height only it will grow/shrink keeping its aspect ratio, but if I want the same effect with another element, is it possible at all to tie the width and the height together using percentage?
5 Answers
You can do this using pure CSS; no JavaScript needed. This utilizes the (somewhat counterintuitive) fact that padding-top
percentages are relative to the containing block's width. Here's an example:
.wrapper {
width: 50%;
/* whatever width you want */
display: inline-block;
position: relative;
}
.wrapper:after {
padding-top: 56.25%;
/* 16:9 ratio */
display: block;
content: '';
}
.main {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
/* fill parent */
background-color: deepskyblue;
/* let's see it! */
color: white;
}
<div class="wrapper">
<div class="main">
This is your div with the specified aspect ratio.
</div>
</div>

- 26,544
- 5
- 58
- 71
-
28i have to say this is awesome, and it even work on IE. big +1 – Peter Aug 25 '12 at 11:03
-
It surely is, never would have though of that :) but why did you delete your jQuery answer? it could be useful too – ilyo Aug 25 '12 at 11:39
-
@Abody97 why would the `padding-top` be related to the width of the element? – ilyo Aug 25 '12 at 21:08
-
2@IlyaD Take a look at this from the CSS2 specification: [little link](http://www.w3.org/TR/CSS21/box.html#propdef-padding-top). – Chris Aug 25 '12 at 21:24
-
Thanks! Is it possible to make it vice versa: let the width depend on the height? – Andrej Jul 08 '13 at 11:37
-
8You, sir, have won the Internet. This is huge, especially for background images on responsive designs. Thank you! – Vidal Quevedo Oct 11 '13 at 23:27
-
50For the mathematically impaired like me: to calculate the padding-top percentage of something else than 16:9 ratios, use this formula (for example using a 22:5 ratio where 22 is A and 5 is B): B / (A / 100) = C%. So 22:5 is 5 / .22 = 22.72%. – Dreamdealer Mar 14 '14 at 13:21
-
To those, like me, who hate the fiddles of CSS and JavaScript, this is - I believe - the best solution you'll find (and I've just wasted a morning looking), including within ASP.NET MVC. Many thanks. – Andy Brown Apr 25 '14 at 11:26
-
This isn't exact. It's actually off by 50-200 pixels for those looking for an EXACT aspect ratio. – bryan Jun 02 '14 at 20:20
-
@bryan: Good luck finding anything that isn't an approximation. – BoltClock Dec 05 '14 at 16:38
-
@Chris, may I ask you to have a look at a responsive design related question here : http://tinyurl.com/nadfh2u ? – Istiaque Ahmed Apr 12 '15 at 15:00
-
If html had been designed to only display squares, there wouldn't be web developers, but everyone at home would know the few commands to color and size a square. I don't know why everyone assumes an "element" is just a colored square. In this case, there can't be content in there with all the padding feeling the box. An extra abs-pos element could not contain text normally since it would overflow once it reaches the end. In other words, it won' grow with it. I won't vote it up because it annoys me that I can't even vote it down (since everyone else seem to like colorful squares) – sergio Jul 19 '15 at 18:24
-
Amazing solution to the problem that works brilliantly, wish i could upvote more – Addzy Aug 17 '15 at 13:59
-
1How to set vertically center `` from body ?– Krunal Mevada Sep 21 '15 at 06:42
-
What if I don't want an absolute position? – Rodrigo Ruiz Dec 02 '15 at 07:49
-
Just FYI: Bootstrap 3.2+ uses this approach with classes `embed-responsive` (`wrapper` in this answer) and `embed-responsive-item` (`main` here) it has 2 additional classes like `embed-responsive-16by9` and `embed-responsive-4by3` which has to be added to the wrapper div to determine the required proportions. – biesior Feb 23 '16 at 09:58
-
1Is the display:inline-block necessary? – Trevor Mar 15 '16 at 22:46
-
The only thing I would change here is the "display: block;" on the .wrapper class.. The reason is that inline-block elements produce a few pixel of blank (vertical) space after the element. – dBlaze Oct 28 '16 at 13:00
Bumming off Chris's idea, another option is to use pseudo elements so you don't need to use an absolutely positioned internal element.
<style>
.square {
/* width within the parent.
can be any percentage. */
width: 100%;
}
.square:before {
content: "";
float: left;
/* essentially the aspect ratio. 100% means the
div will remain 100% as tall as it is wide, or
square in other words. */
padding-bottom: 100%;
}
/* this is a clearfix. you can use whatever
clearfix you usually use, add
overflow:hidden to the parent element,
or simply float the parent container. */
.square:after {
content: "";
display: table;
clear: both;
}
</style>
<div class="square">
<h1>Square</h1>
<p>This div will maintain its aspect ratio.</p>
</div>
I've put together a demo here: http://codepen.io/tcmulder/pen/iqnDr
EDIT:
Now, bumming off of Isaac's idea, it's easier in modern browsers to simply use vw units to force aspect ratio (although I wouldn't also use vh as he does or the aspect ratio will change based on window height).
So, this simplifies things:
<style>
.square {
/* width within the parent (could use vw instead of course) */
width: 50%;
/* set aspect ratio */
height: 50vw;
}
</style>
<div class="square">
<h1>Square</h1>
<p>This div will maintain its aspect ratio.</p>
</div>
I've put together a modified demo here: https://codepen.io/tcmulder/pen/MdojRG?editors=1100
You could also set max-height, max-width, and/or min-height, min-width if you don't want it to grow ridiculously big or small, since it's based on the browser's width now and not the container and will grow/shrink indefinitely.
Note you can also scale the content inside the element if you set the font size to a vw measurement and all the innards to em measurements, and here's a demo for that: https://codepen.io/tcmulder/pen/VBJqLV?editors=1100

- 2,207
- 2
- 16
- 18
-
3This is fantastic since you don't need a wrapping element. Great work! – Jim Buck Jul 20 '16 at 16:17
-
3How can I stop the child content from expanding the height of the parent? – Jacob Raccuia Jun 23 '17 at 17:09
-
-
-
Instead of using the clearfix hack you can use display: flow-root or contain: content on the .square element: https://codepen.io/fcalderan/pen/xxRPwgL – Fabrizio Calderan Mar 09 '21 at 09:34
<style>
#aspectRatio
{
position:fixed;
left:0px;
top:0px;
width:60vw;
height:40vw;
border:1px solid;
font-size:10vw;
}
</style>
<body>
<div id="aspectRatio">Aspect Ratio?</div>
</body>
The key thing to note here is vw
= viewport width, and vh
= viewport height

- 11,409
- 5
- 33
- 45
-
2Just a note that if the screen's ratio is different, the element's ratio will be different, losing the aspect ratio. – Ryan Killeen Sep 30 '15 at 01:08
-
9@RyanKilleen except it looks like he is using "vw" for both width and height. So the percentage will still have the same aspect ratio. – christophercotton Oct 01 '15 at 02:44
-
1@christophercotton .... that's what I get for skimming. You're correct. – Ryan Killeen Oct 01 '15 at 14:00
That's my solution
<div class="main" style="width: 100%;">
<div class="container">
<div class="sizing"></div>
<div class="content"></div>
</div>
</div>
.main {
width: 100%;
}
.container {
width: 30%;
float: right;
position: relative;
}
.sizing {
width: 100%;
padding-bottom: 50%;
visibility: hidden;
}
.content {
width: 100%;
height: 100%;
background-color: red;
position: absolute;
margin-top: -50%;
}

- 312
- 1
- 14
(function( $ ) {
$.fn.keepRatio = function(which) {
var $this = $(this);
var w = $this.width();
var h = $this.height();
var ratio = w/h;
$(window).resize(function() {
switch(which) {
case 'width':
var nh = $this.width() / ratio;
$this.css('height', nh + 'px');
break;
case 'height':
var nw = $this.height() * ratio;
$this.css('width', nw + 'px');
break;
}
});
}
})( jQuery );
$(document).ready(function(){
$('#foo').keepRatio('width');
});
Working example: http://jsfiddle.net/QtftX/1/

- 16,453
- 8
- 51
- 77
-
This is great! I am using this script, however, if I use it on multiple DIV's and they each have different heights...once the script kicks in, it adjusts all heights to be the same...I cannot figure out why! Any ideas? I'd like to maintain the aspect ratio like this script does, but maintain the different heights for each. – Michael Giovanni Pumo Oct 02 '13 at 09:52
-
2Because the function applied for a set of elements. The script should handle each element separately. Here is the updated code: http://jsfiddle.net/QtftX/100/ – onetdev Nov 23 '13 at 10:41
-
If you refresh the page the width and height resets again.. How can you block this? – Gilko Apr 24 '14 at 15:05
-