By jackb


2009-09-29 23:11:05 8 Comments

I want to create a div that can change its width/height as the window's width changes.

Are there any CSS3 rules that would allow the height to change according to the width, while maintaining its aspect ratio?

I know I can do this via JavaScript, but I would prefer using only CSS.

div keeping aspect ratio according to width of window

21 comments

@Salman A 2018-07-03 10:20:22

This is an improvement on the accepted answer:

  • Uses pseudo elements instead of wrapper divs
  • The aspect ratio is based on the width of the box instead of its parent
  • The box will stretch vertically when the content becomes taller

.box {
  margin-top: 1em;
  margin-bottom: 1em;
  background-color: #CCC;
}

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}

.fixed-ar-16-9::before {
  padding-top: 56.25%;
}
.fixed-ar-3-2::before {
  padding-top: 66.66%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-1-1::before {
  padding-top: 100%;
}

.width-50 {
  display: inline-block;
  width: 50%;
}
.width-20 {
  display: inline-block;
  width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>

@Andrei Gheorghiu 2018-11-11 03:44:22

I stumbled upon a smart solution using <svg> and display:grid.

Grid element allows you to occupy the same space with two (or more) elements, without needing to specify which one sets the height. Which means that, out of the box, the taller one sets the ratio.

This means you can use it as is when you know the content will never be tall enough to fill the entire "ratio" and you're simply looking for a way to position the content in this space (i.e. to center it on both directions use display:flex; align-items:center; justify-content:center).
It's pretty much the same as using a transparent <img> with display:block and predetermined ratio, except the <svg> is lighter and considerably easier to modify (to change the ratio responsively, should you need to).

<div class="ratio">
  <svg viewBox="0 0 1 1"></svg>
  <div>
    I'm square
  </div>
</div>
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

All you need to do is change the <svg>s ratio:

  • <svg viewBox="0 0 4 3"></svg>
  • <svg viewBox="0 0 16 9"></svg>

See it working:

.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

/* below code NOT needed for setting the ratio 
 * I just wanted to mark it visually
 * and center contents
 */
.ratio div {
  border: 1px solid red;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="ratio">
  <svg viewBox="0 0 7 1"></svg>
  <div>
    Fixed ratio 7:1
  </div>
</div>


If you need a solution where the content element is not allowed to set the ratio when it's taller (with overflow hidden or auto), you need to set position:relative on the grid and position:absolute; height:100%; overflow-y: auto; on the content. Example:

.ratio {
  display: grid;
  position: relative;
}
.ratio > * {
  grid-area: 1/1/1/1;
}


.ratio > div {
  height: 100%;
  overflow-y: auto;
  position: absolute;
  
  /* the rest is not needed */
  border: 1px solid red;
  padding: 0 1rem;
}
<div class="ratio">
  <svg viewBox="0 0 7 1"></svg>
  <div>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. A scelerisque purus semper eget. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. A cras semper auctor neque vitae tempus quam pellentesque nec. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Arcu odio ut sem nulla. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Cras tincidunt lobortis feugiat vivamus at augue eget. Laoreet sit amet cursus sit amet. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Leo in vitae turpis massa sed elementum tempus egestas sed. Egestas integer eget aliquet nibh. Dolor sit amet consectetur adipiscing elit.

<p>Ut aliquam purus sit amet. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Diam in arcu cursus euismod quis viverra nibh. Nullam vehicula ipsum a arcu cursus vitae congue. Vel orci porta non pulvinar neque laoreet suspendisse. At tellus at urna condimentum mattis pellentesque. Tristique senectus et netus et malesuada. Vel pretium lectus quam id leo in. Interdum velit euismod in pellentesque. Velit euismod in pellentesque massa placerat duis. Vitae suscipit tellus mauris a diam maecenas sed enim.

<p>Mauris a diam maecenas sed enim ut sem. In hendrerit gravida rutrum quisque. Amet dictum sit amet justo donec enim diam. Diam vulputate ut pharetra sit amet aliquam id. Urna porttitor rhoncus dolor purus non enim praesent. Purus in massa tempor nec feugiat nisl pretium. Sagittis vitae et leo duis ut. Facilisi nullam vehicula ipsum a arcu cursus vitae congue mauris. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Aliquam purus sit amet luctus venenatis lectus magna. Sit amet purus gravida quis blandit turpis. Enim eu turpis egestas pretium aenean. Consequat mauris nunc congue nisi. Nunc sed id semper risus in hendrerit gravida rutrum. Ante metus dictum at tempor. Blandit massa enim nec dui nunc mattis enim ut.
  </div>
</div>

@Syed 2018-10-31 10:24:12

Say that you to maintain Width: 100px and Height: 50px (i.e., 2:1) Just do this math:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}

@Web_Designer 2012-05-04 01:19:53

Just create a wrapper <div> with a percentage value for padding-bottom, like this:

div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}
<div></div>

It will result in a <div> with height equal to 75% of the width of its container (a 4:3 aspect ratio).

This relies on the fact that for padding :

The percentage is calculated with respect to the width of the generated box's containing block [...] (source: w3.org, emphasis mine)

Padding-bottom values for other aspect ratios and 100% width :

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

Placing content in the div :

In order to keep the aspect ratio of the div and prevent its content from stretching it, you need to add an absolutely positioned child and stretch it to the edges of the wrapper with:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

Here's a demo and another more in depth demo

@Anson Kao 2012-09-17 20:33:31

@schellmax, it is because padding % is calculated relative to the current element's width, where as height % is calculated relative to the parent element's height. Furthermore, absolute positions are calculated relative to the outside container of an element, which includes the padding area. For more information Google "CSS Box Model"

@Misterparker 2013-02-08 15:53:35

This does not seem to work in a nested fashion. It works at the first level, but when trying to do the same thing inside of the div maintaining aspect ratio, the padding-bottom percentage seems to get applied to the width of the parent. here is an example where the .stretchy-wrap.onethird padding-bottom of 25% is actually 25% of the parent width. Can someone explain this?

@steveluscher 2013-02-20 00:54:50

Totally awesome. It's killing me that this technique won't work when you want to fix the height at 100%. @Misterparker, the technique relies on the width and padding calculations being performed against the same reference; you can't use a width smaller than 100%, as you have in your example.

@Web_Designer 2013-02-20 04:21:36

@Misterparker Yes, percentage padding is calculated in proportion to the parent element's width. See the more in depth example I posted in an edit to my answer. My updated demo demonstrates a 'nested fashion' as you were speaking of.

@Web_Designer 2013-02-20 04:25:48

@steveluscher If you modify the technique a tad, you can do the same with percentages less than 100%. See the more in depth example I posted in an edit to my answer.

@user595349 2013-10-16 22:47:15

the fact that he has demonstrated that this works is enough to convince me that this is the best answer ive yet seen on SO. shout out to my man @Web_Designer

@mindplay.dk 2014-02-02 19:39:36

Note that, in many cases, top:0; bottom:0; is enough - in my case, I have width:999999px on the child element, which lets me create a horizontal strip of <img> tags in the container; with height:100% on those, they hug the container and scale fluently to fit the browser width while preserving aspect ratio. Awesome!

@Daniel Bonnell 2015-05-30 17:54:51

+1 Brilliant solution! I just used padding-bottom: 66.66% without specifying top, bottom, left, or right and it works great!

@Stijn de Witt 2015-06-19 16:44:03

Could we use this with (negative) margin instead of padding to achieve aspect rations where height is larger than width?

@sergio 2015-07-19 18:31:30

Why everyone asumes an "element" is just "a drawing of a box on top of things that are trying to make sense"? Elements are meant to have content, and in this case, putting content (in the secondary abs-pos box) would STOP behaving as a text CONTAINER. It's like one of those asian subways where people have to be PUSHED inside to fit, but open in the back, like "i don't care where people fall at the other side, but I just get them off the station". So this text box now acts rather like text DEFLECTOR, no container. Any text in there will spill at the bottom and it won't grow as a NORMAL div will

@Omid 2015-08-21 12:43:24

Best Answer i have ever seen

@Ethan 2015-11-26 09:06:49

One must read this article on A List Apart, which explains this clearly (cr 2011): alistapart.com/article/creating-intrinsic-ratios-for-video

@Domenico Monaco 2016-06-12 16:15:58

i don't like this solution because you use "Padding" and this interferes with a content.

@Web_Designer 2016-06-14 03:26:07

@Kiuz How does it interfere with the content when you have the inner <div> with position: absolute; top: 0; bottom: 0; left: 0; right: 0; as mentioned in the answer?

@Kim T 2016-06-29 21:50:58

You can also use a psuedo element e.g. &:before { content: ''; display: block; padding-bottom: 56.25%; }

@Marie 2017-02-08 07:24:04

@web-designer on the first demo (dabblet.com/gist/2590942) when I reduce the height of the browser, the blue rectangle does not stay in view, it should auto-resize. Now one has to scroll, why is that?

@Web_Designer 2017-02-08 23:49:45

@Marie That is because, as mentioned in the answer, with this solution both the width and height will be calculated with respect to the width of its parent. If you want a solution where your browser viewport height also constrains the size have a look at the vmin unit.

@Marie 2017-02-09 05:38:49

@web-designer nice to hear from you, I did a bit of guess work last night by looking at the square example css-tricks.com/scaling-responsive-animations and the following css, indeed with vmin, is providing better behavior, again the 44 and 55px are guesses of the ionic2 framework header and tabs-footer (of course lots of this CSS, JS, ... is just beyond my brain) ``` #AMSImage{ width: calc(80vmin - 44px - 50px); // 80vmin; height: calc(60vmin - 44px - 50px); //60vmin; background: beige; // will show on transparent PNG images }```

@Deepak Kamat 2017-11-20 14:25:22

How do I calculate what percentage I have to use based on an aspect ratio, for example 25:12 ?

@MrSwed 2017-12-18 11:09:16

An example based on : jsfiddle.net/r42b0ups/4. Worked in Chrome and last Mozilla. And If needs flexible aspected items, jsfiddle.net/r42b0ups/8 it not worked at Mozilla

@David Harkness 2018-09-20 23:13:41

@DeepakKamat Subtract the height H (12) from the width W (25) to get the padding P (13); then calculate that as a percentage of the width (100 * 13 / 25 = 52%).

@Blue Tram 2019-02-25 10:31:00

Thank you so much! It helps improve my interface skills :)

@user1410288 2018-04-03 11:47:06

You can use the flux layout (FWD).

https://en.wikipedia.org/wiki/Adaptive_web_design

It will scale and maintain the layout, its a bit complex but allows for a page to resize without pushing the content like (RWD).

It looks like responsive but it is scaling. https://www.youtube.com/watch?v=xRcBMLI4jbg

You can find the CSS scaling formula here:

http://plugnedit.com/pnew/928-2/

@Flimm 2018-05-29 15:01:10

How does this answer the question?

@wener 2017-11-01 02:40:25

As @web-tiki already show a way to use vh/vw, I also need a way to center in the screen, here is a snippet code for 9:16 portrait.

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateY will keep this center in the screen. calc(100vw * 16 / 9) is expected height for 9/16.(100vw * 16 / 9 - 100vh) is overflow height, so, pull up overflow height/2 will keep it center on screen.

For landscape, and keep 16:9, you show use

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

The ratio 9/16 is ease to change, no need to predefined 100:56.25 or 100:75.If you want to ensure height first, you should switch width and height, e.g. height:100vh;width: calc(100vh * 9 / 16) for 9:16 portrait.

If you want to adapted for different screen size, you may also interest

  • background-size cover/contain
    • Above style is similar to contain, depends on width:height ratio.
  • object-fit
    • cover/contain for img/video tag
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Media query for portrait/landscape to change the ratio.

@web-tiki 2014-05-15 08:48:00

vw units:

You can use vw units for both the width and height of the element. This allows the element's aspect ratio to be preserved, based on the viewport width.

vw : 1/100th of the width of the viewport. [MDN]

Alternatively, you can also use vh for viewport height, or even vmin/vmax to use the lesser/greater of the viewport dimensions (discussion here).

Example: 1:1 aspect ratio

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
<div></div>

For other aspect ratios, you can use the following table to calculate the value for height according to the width of the element :

aspect ratio  |  multiply width by
-----------------------------------
     1:1      |         1
     1:3      |         3
     4:3      |        0.75
    16:9      |       0.5625

Example: 4x4 grid of square divs

body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>

Here is a Fiddle with this demo and here is a solution to make a responsive grid of squares with verticaly and horizontaly centered content.


Browser support for vh/vw units is IE9+ see canIuse for more info

@Isaac 2014-05-15 09:40:51

How am I only seeing this now...

@aug 2015-01-23 05:44:16

This should be the accepted answer. Perhaps not now, but in the future. vw units are supported in most browsers now.

@Vivek Maharajh 2015-04-09 01:50:15

seems better than the accepted stretchy div answer

@web-tiki 2015-04-22 11:46:35

@vivekmaharajh both techniques are good, each one has it's own pros and cons. Using one or the other depends greatly on the situation.

@Vivek Maharajh 2015-04-29 17:55:57

@web-tiki, you are right. I've run into one issue - it assumes that the element's width is proportional to the viewport's width, which won't be the case if 1) you've got things like fixed width gutters, or 2) you have max-width set for some of your elements.

@Tormod Haugene 2015-08-25 06:12:34

Thanks for introducing a use case for the "new" size units!

@thdoan 2015-10-26 07:23:30

Maybe it's just Chrome v47beta, but when I set the div to width:50% and height:50vw the height is a little bit taller than the width, so not exactly a 1:1 proportion. Any ideas?

@web-tiki 2015-10-26 10:09:24

@10basetom it is a normal behaviour. vw units contain the scrollbar width whereas % width doesn't. The difference between height and width will depend on the size of the scrollbar which is different depending on browser.

@azariah 2015-11-23 07:19:11

Wow epic solution. Can't believe this was staring me in the face. I've already used these units for some font sizing can't believe it didn't occur to me to use them for this. Also just realised I can replace a good chunk of my JS stylesheet interactions. :)

@davidmars 2016-06-13 02:18:10

I love vh/vw units concept... Except on iOS devices. That´s why the padding solution is my favorite for now.

@IanB 2017-06-19 09:19:44

In case anyone else is wondering: 16:9 ratio as CSS is width: 100%; height: 56.25vw;

@Matvey Andreyev 2017-10-11 09:27:37

vw unit is good only in some cases. Imagine you've made your site 100% width and using vw units for elements with fixed proportion, then the client asks you to fix your main container's max-width. If you used the padding solution, it would be enough just to fix that max-width. With vw, you will have to rewrite corresponding styles to the padding solution then.

@user10089632 2017-12-29 08:54:18

The accepted answer is a smart hack back then, but this is the standard way to do it.

@Peter 2018-01-29 10:08:34

This answer is infinitely superior to the one with the most votes. What were people thinking? Once you set the padding then you have to invent another hack to get the divs underneath to move up and align. Not a solution IMHO.

@Parker Ault 2018-02-15 23:00:04

@Peter the original answer was written in 2012 before vw/vh were implemented (or even invented, most likely). :)

@DavidTaubmann 2018-03-24 21:44:41

@Peter This metric doesn't imply aspect ratio from available width for the element, only for the size of the viewport. The size of an element is much more relative to the space available inside the current parent than the space of the viewport, that's why the other answer is more voted.

@gzimmers 2019-04-01 17:32:41

This should be the accepted answer, fantastic aspect ratio scaling as well as accounting for viewport sizing i.e. responsiveness. Thank you!

@MoonLite 2017-06-16 13:07:16

If you want to fit a square inside the viewport on either portrait or landscape view (as big as possible, but nothing sticking outside), switch between using vw/vh on orientation portrait/landscape:

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 

@user007 2017-04-13 21:44:27

I have run into this issue quite some times, so I made a JS solution for it. This basically adjust the height of the domElement according the width of the element by the ratio you specify. You could use it as followed:

<div ratio="4x3"></div>

Please be aware that since it is setting the height of the element, the element should be either a display:block or display:inline-block.

https://github.com/JeffreyArts/html-ratio-component

@Theo d'Or 2017-11-13 21:12:16

Although I haven't seen or tried your code (I already have my own) I have upvoted your answer just for the fact that you present the only reliable solution, a JS script.

@Flimm 2018-05-29 15:02:18

The question specifically asked for a solution that didn't need Javascript.

@Salketer 2017-01-16 13:41:47

While most answers are very cool, most of them require to have an image already sized correctly... Other solutions only work for a width and do not care of the height available, but sometimes you want to fit the content in a certain height too.

I've tried to couple them together to bring a fully portable and re-sizable solution... The trick is to use to auto scaling of an image but use an inline svg element instead of using a pre-rendered image or any form of second HTTP request...

div.holder{
  background-color:red;
  display:inline-block;
  height:100px;
  width:400px;
}
svg, img{
  background-color:blue;
  display:block;
  height:auto;
  width:auto;
  max-width:100%;
  max-height:100%;
}
.content_sizer{
  position:relative;
  display:inline-block;
  height:100%;
}
.content{
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(155,255,0,0.5);
}
<div class="holder">
  <div class="content_sizer">
    <svg width=10000 height=5000 />
    <div class="content">
    </div>
  </div>
</div>

Notice that I have used big values in the width and height attributes of the SVG, as it needs to be bigger than the maximum expected size as it can only shrink. The example makes the div's ratio 10:5

@Eshwaren Manoharen 2016-01-28 18:04:15

I used a new solution.

.squares{
  width: 30vw
  height: 30vw

To main aspect ratio

.aspect-ratio
  width: 10vw
  height: 10vh

However, this is relative to the entire viewport. So, if you need a div that is 30% of the viewport width, you can use 30vw instead, and since you know the width, you reuse them in height using calc and vw unit.

@rnevius 2016-01-29 13:01:25

Isn't this exactly what the second-highest rated answer already outlined?

@pie6k 2013-12-05 21:13:26

Basing on your solutions I've made some trick:

When you use it, your HTML will be only

<div data-keep-ratio="75%">
    <div>Main content</div>
</div>

To use it this way make: CSS:

*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

and js (jQuery)

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

And having this you just set attr data-keep-ratio to height/width and that's it.

@Robert 2016-07-14 20:06:51

you should use data-keep-ratio not keep-ratio and get it's value using $(this).data('keep-ratio');

@Robert 2016-07-14 20:08:51

your code is working now and maybe will work forever but it's not standard and browsers may stop supporting it anytime in the future

@Amir Hossein Ahmadi 2018-06-15 11:35:52

Using JS here will cause bad news!

@Maciej Krawczyk 2016-10-05 05:26:40

You can use an svg. Make the container/wrapper position relative, put the svg first as staticly positioned and then put absolutely positioned content (top: 0; left:0; right:0; bottom:0;)

Example with 16:9 proportions:

image.svg: (can be inlined in src)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

<div class="container">
  <img style="width: 100%" src="image.svg" />
  <div class="content"></div>
</div>

Note that inline svg doesn't seem to work, but you can urlencode the svg and embed it in img src attribute like this:

<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />

@aeid 2016-09-15 02:04:36

lets say you have 2 divs the outher div is a container and the inner could be any element that you need to keep its ratio (img or an youtube iframe or whatever )

html looks like this :

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->

lets say you need to keep the ratio of the "element"

ratio => 4 to 1 or 2 to 1 ...

css looks like this

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/

}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

padding when specified in % it is calculated based on width not height. .. so basically you it doesn't matter what your width it height will always be calculated based of that . which will keep the ratio .

@gordie 2015-10-23 11:18:14

SCSS is the best solution in my case; using a data attribute :

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;

    &:before {
        content: '';
        display: block;
    }

    > * {
        display: block;
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;
    }
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

For example :

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

source

@rnevius 2015-10-23 16:39:34

Just FYI...You can do this exact thing (using attribute selectors) in exactly the same amount of lines using plain CSS. The [data-aspect-ratio] attribute selector is available to you in CSS.

@Orland 2015-09-30 15:43:57

Just an idea or a hack.

div {
  background-color: blue;
  width: 10%;
  transition: background-color 0.5s, width 0.5s;
  font-size: 0;
}

div:hover {
  width: 20%;
  background-color: red;
}
  
img {
  width: 100%;
  height: auto;
  visibility: hidden;
}
<div>
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />
</div>

@rnevius 2015-09-30 15:48:16

This isn't a CSS-only solution...Now, if you would have used a base64 encoded image in a pseudo element, that would have been a cool solution.

@Orland 2015-09-30 15:49:19

There's really no CSS-only solution. HTML is the basic component of web. I believe the purpose of the question is to refrain from using JS perhaps to save resource/processing.

@Orland 2015-09-30 16:02:48

I'm not sure if pseudo element will work. I utilized the property of img element to keep its aspect ratio for this solution to work.

@Marc A 2015-03-22 12:18:17

As stated in here on w3schools.com and somewhat reiterated in this accepted answer, padding values as percentages (emphasis mine):

Specifies the padding in percent of the width of the containing element

Ergo, a correct example of a responsive DIV that keeps a 16:9 aspect ratio is as follows:

CSS

.parent {
    position: relative;
    width: 100%;
}
.child {
    position: relative;
    padding-bottom: calc(100% * 9 / 16);
}
.child > div {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

HTML

<div class="parent">
    <div class="child">
        <div>Aspect is kept when resizing</div>
    </div>
</div>

Demo on JSFiddle

@forgo 2009-12-22 02:08:49

I've found a way to do this using CSS, but you have to be careful as it may change depending on the flow of your own web site. I've done it in order to embed video with a constant aspect ratio within a fluid width portion of my web site.

Say you have an embedded video like this:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

You could then place this all inside a div with a "video" class. This video class will probably be the fluid element in your website such that, by itself, it has no direct height constraints, but when you resize the browser it will change in width according to the flow of the web site. This would be the element you are probably trying to get your embedded video in while maintaining a certain aspect ratio of the video.

In order to do this, I put an image before the embedded object within the "video" class div.

!!! The important part is that the image has the correct aspect ratio you wish to maintain. Also, make sure the size of the image is AT LEAST as big as the smallest you expect the video (or whatever you are maintaining the A.R. of) to get based on your layout. This will avoid any potential issues in the resolution of the image when it is percentage-resized. For example, if you wanted to maintain an aspect ratio of 3:2, don't just use a 3px by 2px image. It may work under some circumstances, but I haven't tested it, and it would probably be a good idea to avoid.

You should probably already have a minimum width like this defined for fluid elements of your web site. If not, it is a good idea to do so in order to avoid chopping elements off or having overlap when the browser window gets too small. It is better to have a scroll bar at some point. The smallest in width a web page should get is somewhere around ~600px (including any fixed width columns) because screen resolutions don't come smaller unless you are dealing with phone-friendly sites. !!!

I use a completely transparent png but I don't really think it ends up mattering if you do it right. Like this:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

Now you should be able to add CSS similar to the following:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

Make sure you also remove any explicit height or width declaration within the object and embed tags that usually come with copy/pasted embed code.

The way it works depends on the position properties of the video class element and the item you want have maintain a certain aspect ratio. It takes advantage of the way an image will maintain its proper aspect ratio when resized in an element. It tells whatever else is in video class element to take full-advantage of the real estate provided by the dynamic image by forcing its width/height to 100% of the video class element being adjusted by the image.

Pretty cool, eh?

You might have to play around with it a bit to get it to work with your own design, but this actually works surprisingly well for me. The general concept is there.

@florianb 2012-07-07 14:25:42

Elliot inspired me to this solution - thanks:

aspectratio.png is a completely transparent PNG-file with the size of your preferred aspect-ratio, in my case 30x10 pixels.

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

Please note: background-size is a css3-feature which might not work with your target-browsers. You may check interoperability (f.e. on caniuse.com).

@nabrown 2012-05-06 17:35:13

To add to Web_Designer's answer, the <div> will have a height (entirely made up of bottom padding) of 75% of the width of it's containing element. Here's a good summary: http://mattsnider.com/css-using-percent-for-margin-and-padding/. I'm not sure why this should be so, but that's how it is.

If you want your div to be a width other than 100%, you need another wrapping div on which to set the width:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

I used something similar to Elliot's image trick recently to allow me to use CSS media queries to serve a different logo file depending on device resolution, but still scale proportionally as an <img> would naturally do (I set the logo as background image to a transparent .png with the correct aspect ratio). But Web_Designer's solution would save me an http request.

@Mi-La 2018-02-06 17:37:59

Great solution. In my case I know the "natural" image size when placing it to DOM and I need to have an image placeholder with proper height to prevent further scrolling once the browser loads the images. In .ar-outer I have the image width in pixels, in .ar I have padding-bottom calculated from real image aspect ratio. Instead of ar-inner I have the image itself (<img>). However I had to set width to 100% instead of setting top, bottom, left and right. When I set maxWidth to ar-outer, the image scales nicely when parent is small, but doesn't scale to bigger size than its natural size.

@Nick Craver 2009-09-30 00:52:06

If the entire container structure was percentage based, this would be the default behavior, can you provide a more specific example?

Below is an example of what I mean, if your entire parent hierarchy was % based, any browser window adjustment would work without any additional js/css, is this not a possibility with your layout?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>

@jackb 2009-09-30 15:20:02

See my edit to the original question. I don't see where this technique would keep the aspect ratio, the height would not change.

Related Questions

Sponsored Content

96 Answered Questions

[SOLVED] How to horizontally center a <div>?

33 Answered Questions

[SOLVED] Change an HTML5 input's placeholder color with CSS

31 Answered Questions

[SOLVED] Make a div fill the height of the remaining screen space

  • 2008-09-18 05:06:17
  • Vincent McNabb
  • 805957 View
  • 1550 Score
  • 31 Answer
  • Tags:   html css html-table

26 Answered Questions

[SOLVED] Set cellpadding and cellspacing in CSS?

27 Answered Questions

[SOLVED] Is there a CSS parent selector?

  • 2009-06-18 19:59:36
  • jcuenod
  • 1644070 View
  • 2777 Score
  • 27 Answer
  • Tags:   css css-selectors

29 Answered Questions

[SOLVED] Transitions on the display: property

24 Answered Questions

[SOLVED] Vertically centering a div inside another div

  • 2011-06-27 08:22:03
  • user700284
  • 540795 View
  • 491 Score
  • 24 Answer
  • Tags:   html css html5 css3

19 Answered Questions

[SOLVED] Is it possible to apply CSS to half of a character?

31 Answered Questions

[SOLVED] How to make a div 100% height of the browser window?

  • 2009-10-15 21:18:43
  • mike
  • 1715349 View
  • 1883 Score
  • 31 Answer
  • Tags:   html css css3 height

23 Answered Questions

[SOLVED] How to style a <select> dropdown with only CSS?

Sponsored Content