8

How can I have a div with 100% height that has a particular aspect ratio, e.g. 2:3?

For example, if the outer element has a height of 900px, the width of the inner element should be 600px, but this should be responsive.

I don't want to use any JavaScript for this.

Using the CSS3 flexible box model would be fine.

ancestral
  • 1,851
  • 1
  • 12
  • 7
Andreas Ka
  • 839
  • 9
  • 23
  • There is an ambiguity in your problem. If your div has a portrait-type aspect ratio, giving it 100% height makes sense. If your div is landscape-type, then the width 100% makes sense. Please explain in more detail what you are trying to do. – Marc Audet Sep 14 '13 at 16:32
  • It is a div with a portrait type aspect ratio. I want it to use all the remaining screen height under the header of the page. – Andreas Ka Sep 14 '13 at 23:23
  • How do you figure Flexbox would be suitable for solving this problem? – cimmanon Sep 16 '13 at 19:18
  • Related: http://stackoverflow.com/questions/12121090/responsively-change-div-size-keeping-aspect-ratio – cimmanon Sep 16 '13 at 19:32

2 Answers2

7

If you are targeting modern browsers that support CSS3, you can try the following.

Consider the following HTML snippet:

<div class="wrapper">
    <div class="inner">Inner content...</div>
</div>

and apply the following CSS rules:

html, body {
    height: 100%;
}
body {
    margin: 0;
}
.wrapper {
    background-color: lightblue;
    height: 100%;
}
.wrapper .inner {
    margin: 0 auto;
    background-color: beige;
    height: 100%;
    width: 66.6666666666vh;
}

The .wrapper element takes up 100% of the view port height because I have set height: 100% on the body and html elements.

The inner wrapper .inner has a height: 100% and fills up the parent block.

To set the .inner width, use the viewport-percentage length vh that scales with the height of the parent block.

In this example, 66.66vh means 66.66% of the vertical height, which corresponds to a 2:3 aspect ratio (width:height).

See demo at jsFiddle

Reference: http://www.w3.org/TR/css3-values/#viewport-relative-lengths

Browser Compatibility
The vh unit and other vertical percentage lengths have pretty good support with the latest browsers, see the reference below for more details.

See reference:
https://developer.mozilla.org/en-US/docs/Web/CSS/length#Browser_compatibility

Alternative Approach Using a Spacer Image

Consider the following HTML:

<div class="ratio-wrapper">
    <img class="spacer" src="http://placehold.it/20x30">
    <div class="content">Some content...</div>
</div>

and apply the following CSS:

.ratio-wrapper {
    position: relative;
    display: inline-block;
    border: 1px solid gray;
    height: 500px; /* set the height or inherit from the parent container */
}
.ratio-wrapper .spacer {
    height: 100%; /* set height: 100% for portrait style content */
    visibility: hidden;
    vertical-align: top;
}
.ratio-wrapper .content {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    padding: 20px;
}

The .ratio-wrapper container has two child elements, an img.spacer and div.content. The image as a portrait aspect ratio, for example, 20x30 (wxh) and is set to expand to fill the height of the parent container using height: 100%. The image is hidden from view but retains its space in the parent block.

The .content element is positioned absolutely to fill the parent container and can contain any content. Because .content is constrained in height and width, the content could overflow in some cases, so setting overflow: auto may be appropriate.

See demo at: http://jsfiddle.net/audetwebdesign/BVkuW/

Related question and answer:
In Fluid Container, Can I Make Elements as Tall as they Are Wide?

Community
  • 1
  • 1
Marc Audet
  • 46,011
  • 11
  • 63
  • 83
  • This is exactly what I was looking for, great! The only issue is that vh units currently not seem to be supported in the Android browser. Is there any workaround for Android? I was planning to support mobile browsers (Android from version 3, Webkit, Firefox) and modern web browsers that support the flexible box model. – Andreas Ka Sep 15 '13 at 02:41
  • I updated my answer with a reference to an earlier answer that I posted on another question that shows another technique for creating a responsive div with a specified aspect ratio. – Marc Audet Sep 15 '13 at 13:49
  • @cimmanon I am not sure if flex box is relevant here, I have not had much experience with it. The OP wants to support the Android browser and I have run out of ideas! The OP mentioned flex box and I was referring to it in the context of browser support. – Marc Audet Sep 16 '13 at 19:51
  • @cimmanon I updated my post taking into account your comments. You have a valid point. Thank you for your help! – Marc Audet Sep 16 '13 at 20:08
  • Thanks for your answer. The 2nd link you posted is filling the parents elements width, no the parents elements height as required. Same for the link cimmanon was posting. also vh and vw units are not really what I am looking for since they refer to the viewport height/width and not to the parents element height width. I was looking for other approaches, but could not find any. It seems having a child element that would fill the parent elements height while keeping a particular aspect ratio is currently not possible with css only. Thank you very much for your efford anyway. – Andreas Ka Sep 18 '13 at 11:31
  • The alternative approach that I referred to can be modified for child elements that need to fill the parent's height. Please see the updated answer for a demonstration of the technique. – Marc Audet Sep 18 '13 at 14:24
  • Hi the alternative approach almost works :) Except that for some reason if I set the wrapper height to 100% and change the screen height, I have to reload the page until the box is resizing. – Andreas Ka Sep 24 '13 at 13:09
0

You can do this by sticking a 2px by 3px image and an inner div as siblings into an outer div which has display: inline-block; applied. Now when you set the image to have a height of 100%, and you absolutely position the inner div to be as high and wide as its ancestor, you can set the height of the outer div, and the width of all elements involved will be exactly equal and based on the aspect ratio of the image.

Here's a jsFiddle demonstrating this approach.

HTML

<div>
    <div>2 by 3</div>
    <img src=".../twobythree.png" />
</div>

CSS

body > div {
    height: 300px;
    position: relative;
    display: inline-block;
}
img {
    display: block;
    height: 100%;
}
div > div {
    position: absolute;
    top: 0px;
    bottom: 0px;
    left: 0px;
    right: 0px;
}
Mathijs Flietstra
  • 12,900
  • 3
  • 38
  • 67
  • This is basically the what Marc suggested as alternative approach and required a page reload when the height of the outer element or browser would change. – Andreas Ka Sep 24 '13 at 13:17