4

Is there anyway to specify an aspect ratio in CSS such as 4:3 or 16:9 and then have the div (container) block fit the current window width and height?

enter image description here

Quite a simple question hopefully it has a relatively simple answer.

Edit: those still interested a great example of achieving this using only styles would be Bootstrap's responsive helpers classes.

jshbrntt
  • 5,134
  • 6
  • 31
  • 60
  • the answer is `no`. Absolutely – el Dude Jan 10 '14 at 01:09
  • 2
    How about in combination with a little bit of JS? – jshbrntt Jan 10 '14 at 01:11
  • @SyntheCypher No js is needed. its an easy concept, use percentages and padding on the width / height a div within a container to lock the div to the aspect ratio's ratio. – agconti Jan 10 '14 at 01:18
  • 1
    I think this might be the answer to your question. [http://stackoverflow.com/questions/12121090/responsively-change-div-size-keeping-aspect-ratio][1] [1]: http://stackoverflow.com/questions/12121090/responsively-change-div-size-keeping-aspect-ratio – Manoj De Mel Jan 10 '14 at 01:40
  • Nope unfortunately that only works when resizing the width of the window and not the height. [Width (Working)](http://i.imgur.com/RH5xNVM.png), [Height (Not Working)](http://i.imgur.com/0B8xza6.png) – jshbrntt Jan 10 '14 at 15:55

4 Answers4

3

For this I fear you'll need some JS. I used jQuery here:

function preserveAspect() {
  var scaled = $("#scaled");
  scaled.height("100%");
  scaled.width("100%");
  scaled.css("box-sizing", "border-box");
  var ratio = 16/9;
  var w = scaled.outerWidth();
  var h = scaled.outerHeight();

  if (w > ratio*h) {
    scaled.width(ratio*h);
    // horizontal centering is done using margin:auto in CSS
  } else if (h > w/ratio) {
    var newHeight = w/ratio;
    scaled.height(newHeight);
    // for vertical centering:
    scaled.css({marginTop: ($("body").height()-newHeight)/2});
  }

}
$(document).ready(function() {
    preserveAspect();
    $(window).resize(preserveAspect);
});

Explanation:

  1. First we scale up our div to 100% in width and height so that we know how much space it has.
  2. Then we look up if it is too wide which means that the width is more than height times ratio.
    • If so, change width. Height is at 100% already.
    • Otherwise it might be too high, in which case we want the scale to be width divided through ratio. To center vertically we use a margin-top set to (window_height - element_height) / 2.
  3. If neither of both rules apply, the div is scaled properly already.
  4. In the end we add event listeners for when document is fully loaded and whenever the window size changes.

Full code and working example here: http://jsbin.com/efaRuXE/5/

Hubert Grzeskowiak
  • 15,137
  • 5
  • 57
  • 74
  • replace "scaled.height("100%"); scaled.width("100%");" by scaled.css({ 'height': '100%', 'width': '100%' }); or else it fails on divs with box-sizing: border-box – Maria Feb 10 '16 at 04:34
  • @JohnLee I just tested with Firefox 44 and it works for me even with border-box. What browser did you use? – Hubert Grzeskowiak Feb 10 '16 at 04:43
  • @HubertGrzeskowiak If the border-box div has a border (ex: border: 5px solid yellow), scaled.height("100%") would make the div have a higher number than 100% in its inline-style; I used Chrome btw. – Maria Feb 10 '16 at 19:40
  • Tried your solution and it didn't work for me in FX. Added box-sizing instead. – Hubert Grzeskowiak Feb 15 '16 at 10:18
  • @HubertGrzeskowiak can you modify the same with scaling element. Means maintain the text line to line. I need to implement same functionality with scaling element but text will stay same. – Gitesh Purbia Sep 09 '17 at 10:26
  • @GiteshPurbia sounds like a different problem. Please open a new question and provide the whole story (problem, target solution, what you tried). – Hubert Grzeskowiak Sep 11 '17 at 04:45
  • @HubertGrzeskowiak thanks for you reply. I achieved that thing from here https://codepen.io/cRckls/pen/mcGCL. this is same example what you provide but scaling element, to keep text as it is. – Gitesh Purbia Sep 11 '17 at 05:38
3

This question's a few weeks old now, but there is a pure CSS way to accomplish this. Thanks to Danield for using it to answer this question. It uses the vw and vh units, like so:

#wrapper {
    height:75vw;
    max-height:100vh; /* max-height / height = aspect ratio */
    width:100vw;
    max-width:133.3333vh; /* max-width / width = aspect ratio */
    position:absolute;
}

The bad news is that support is iffy in current mobile browsers and in IE before version 11.

Community
  • 1
  • 1
  • This is pure genius, and works perfect for me, I guess the browsers caught up, and makes this easily the best solution! – TeeJaay Mar 07 '18 at 22:56
2

Found a way. This may be rough but it should get you going. Set the element's height to zero and then use a percentage for the padding.

jsFiddle example

For example, 4:3:

div {
    height: 0;
    padding-bottom: 75%;
    background: #999;
}

For example, 16:9

div {
    height: 0;
    padding-bottom: 56%;
    background: #999;
}
j08691
  • 204,283
  • 31
  • 260
  • 272
  • That only works for window width once you resize the window's height past the aspect it gets clipped. Also if I wanted to resize sub-elements relative to percentages it won't work because the height is 0. [Picture](http://i.imgur.com/Ij505tT.png) Thanks anyway. – jshbrntt Jan 10 '14 at 01:16
  • 1
    Well what would you expect if the ratio is fixed but the window can't contain it? The ratio is supposed to magically change? – j08691 Jan 10 '14 at 01:17
  • Well it can scale down to fit the window, leaving whitespace on either side of it. – jshbrntt Jan 10 '14 at 01:20
  • 1
    1+ I'm surprised nobody has upvoted this yet.. I've used this method for years; it works perfectly when maintaining the aspect ratio on responsively embedded youtube videos. – Josh Crozier Jan 10 '14 at 02:29
  • See my image I added to the original post is is fine but doesn't work when resizing the height of the window. – jshbrntt Jan 10 '14 at 15:45
0

Unfortunately no.

I've proposed once on www-styles WG @ W3C construction like this:

div {
  width: 50%;
  height: width(56.25%); /* 16:9 ratio */
}

but no one from browser vendors expressed any interest at that moment.

And anyway that solution above allows to define ratio of boxes only. But layout model used by CSS does not allow to define inscribing declaratively.

c-smile
  • 26,734
  • 7
  • 59
  • 86