Maintain the aspect ratio of a div with CSS

0 votes
asked Sep 29, 2009 by jackb

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

16 Answers

0 votes
answered Jan 30, 2009 by nick-craver

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>
0 votes
answered Sep 22, 2009 by forgo

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.

0 votes
answered Sep 4, 2012 by web-designer

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>
0 votes
answered Sep 6, 2012 by nabrown78

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.

0 votes
answered Sep 7, 2012 by florianb

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).

0 votes
answered Sep 5, 2013 by pie6k

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.

0 votes
answered Sep 15, 2014 by web-tiki

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>
0 votes
answered Sep 22, 2015 by marc-a

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

0 votes
answered Sep 23, 2015 by gordie

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

0 votes
answered Sep 30, 2015 by orland

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>
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...