3

I have a div (#outer) that's placed in the middle left section of the web browser (Chromium). It's width can change as the window resizes. The outer div has another div inside that I want to resize with a fixed aspect ratio (16:9) while always staying in the bounds of the outer div.

For example, if the outer div resizes to tall and thin, the inner div should fit the full width of the outer div while maintaining the proportional height. If the outer div resizes to short and wide, the inner div should fit the full height of the outer div with proportional width. The inner div shouldn't stretch outside of the the outer div's bounds and there shouldn't be scrollbars.

Essentially, I want to accomplish what was asked here, but contained within another dynamically changing div, and not just the viewport. I tried using the viewport vw and vh, but haven't gotten it to work within a div. I'm currently using a before element with padding-top: 56.25%, which works only with respect to the width of the outer div and overflows the outer div if the width is much larger than the height.

Ideally, I'd like to use pure CSS, but I'm willing to write javascript if there is no alternative. Any ideas? Thanks!

Relevant HTML:

<div id="outer">
    <div class="box"><div id="camera_view"></div></div>
</div>

Relevant CSS:

Using a before element:

.box {
    position:relative;
    width: 100%;
    height: 100%;
}

.box:before {
    content: "";
    display: block;
    padding-top: 56.25%;
    background: #A2E8A7;
}

.box-content {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
}

#outer {
    display: flex;
    position: relative;
    width: 100%;
    align-items: center;
}

Using viewport units: (edit: this as a separate test file)

.box {
    width: 100vw; 
    height: 56.25vw;
    background: #FF8AB1;
    max-height: 100vh;
    max-width: 177.78vh;
    margin: auto;
    position: absolute;
    left:0;right:0;
}

#outer {
    width: 50%; 
    height: 50%;
    /* edit: 50% only used to mimic the approximate size of #outer */
}

.box-content {
    background: #FF8AB1;
}
Community
  • 1
  • 1
Valka
  • 33
  • 1
  • 6
  • Which div should keep the 16:9 aspect ratio? `#box`? – umop aplsdn Jul 06 '15 at 19:29
  • In "Using a before element", what should be the height of #outer? – Yandy_Viera Jul 06 '15 at 19:31
  • Tyler - yes, #box should keep the 16:9 ratio. – Valka Jul 06 '15 at 19:39
  • YandY - height of #outer would be the height of it's parent (not shown), but #outer is about 60% of the window's height – Valka Jul 06 '15 at 19:41
  • 1
    mantain ratio http://stackoverflow.com/questions/1495407/how-to-maintain-the-aspect-ratio-of-a-div-using-only-css – ncubica Jul 06 '15 at 19:50
  • ncubica - yes, I've tried what that thread suggested, but it only works within the window, not a wrapper div that has been placed somewhere already within a page. In that suggested solution, since the ratio is determined by the width of the div, the div who's aspect ratio I want to maintain will overflow the height of the outer div if the outer div's width grows large. – Valka Jul 06 '15 at 20:10
  • thanks for the reply @KevinNelson but I didn't ask the question was valka lol ;) – ncubica Jul 06 '15 at 21:30
  • @ncubica, sorry...not enough sleep or caffeine today apparently...and I've more or less determined that's not the problem, so delete that comment. Thx. – Kevin Nelson Jul 06 '15 at 21:34

2 Answers2

1

I know that you really want a pure CSS solution and I really hope that someone give you a css solution, the big problem is to set the width in function of the parent's height, see my question here Setting the width depending on the height of its parent.

Here a solution using js:

function setAspectRatio(){
    var outer = $('#outer');
    var box = $('.box');

    if (outer.height() > outer.width() * 0.5625) {
        box.css({'width': '100%'});
        box.css({'height': box.width() * 0.5625});

    } else {
        box.css({'height': '100%'});
        box.css({'width': box.height() / 0.5625});
    }
}

$(document).ready(function() {
    setAspectRatio();

    $(window).resize(function() {
        setAspectRatio();
    })
})
.box {
    position:relative;
    background: #A2E8A7;
    margin: 0px auto;
}
.box-content {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
}
#outer {
    display: flex;
    position: relative;
    width: 100%;
    height: 60vh;
    align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="outer">
    <div class="box">
        <div id="camera_view"></div>
    </div>
</div>

Here a jsfiddle to play with

I hope this help you

Community
  • 1
  • 1
Yandy_Viera
  • 4,320
  • 4
  • 21
  • 42
  • Thanks for your sample! From fiddle, it looks like what I want to recreate. I will test this in my code and let you know if I got it to work properly. – Valka Jul 06 '15 at 22:12
  • Yes, this incorporates well into my current code. Thank you! I'm still working out a pure css solution as well. – Valka Jul 06 '15 at 23:54
  • @Valka I'm glad to help you, if you find a pure css solution, I would be grateful if you let me know :) – Yandy_Viera Jul 07 '15 at 03:50
0

I'm trying to recreate your layout where you are saying that you have it on the side and when it shrinks too much, it overflows. I can't reproduce that effect. Using the link here: Maintain the aspect ratio of a div with CSS, I was able to get things to work fine as far as I can tell. Can you do a bootply, or dabblet to reproduce the problems if the below doesn't work???

Here's a CodePen link for the below.

    <!doctype html>
<html>
    <head>
        <style type='text/css'>

            html, body {
                height: 100%;
                width: 100%;
                position: relative;
            }
            #container { width:100%;height:100%;min-width:480px; }
            #outer_wrapper {
              width:100%;
              height:100%;
              margin:0 auto;
            }
            #outer {
                position: relative;
                width: 100%;
                align-items: center;
                background: black;
                padding-bottom: 56.25%;
                margin: 0 auto;
            }
            .box {
                position: absolute;
                top: 0; bottom: 0; left: 0; right: 0;
                background: #83E1D1;
            }
            #topbar { height:26px;background-color:#600; }
            #bottombar { height:20px;background-color:#006; }
            #content_wrapper {
                width:100%;height:100%;
            }
            #content_left {
                width:auto;
                margin-right:280px;
            }
            #info { background-color:#006;color:white;}
            #content_right {
                float:right;
                width: 280px;
                height:100%;
                background: #d43b89;
            }
            #bottombar {
                position:fixed;bottom:0;left:0;right:0;height:20px;background:#000;
            }
        </style>

    </head>
    <body>
        <div id="container">

            <div id="topbar">
                <div id="title"><a href="/">Lorem Ipsum</a></div>
            </div>

            <div id="content_wrapper">
                <div id="content_right">
                    &nbsp;
                </div>
                <div id="content_left">
                    <div id='outer_wrapper'>
                        <div id='outer'>
                            <div class='box'>
                                <div id="camera_view">Hello World</div>
                            </div>
                        </div>
                    </div>
                    <div id='info'>Info below camera view</div>
                </div>
            </div>

            <div id="bottombar">
            </div>

        </div>

    </body>
</html>

UPDATE

Since you need it to STOP at a certain size (because the height is fixed for the outer area) and not get any bigger, you need to determine at what height you need it to stop...then make the #outer-wrapper that I've created in my example to stop at that max-width and max-height. I've updated the Code Pen to work this way:

http://codepen.io/anon/pen/XbEebm

UPDATE 2 I've updated the above CodePen (here) to be more like your layout. This is about as far as I can go in helping you. My opinion is to avoid absolutes unless there is absolutely no way that you can avoid them...they don't respect the position of other tags...so primarily what I've done is create the layout of your example without anything absolutely positioned except for the camera view part.

You may also notice I put a min-width on the #container to prevent the 16/9 from becoming too small...you may want to change the min-width a bit, but you will probably need one to prevent overflow from within that area when it gets too small.

Community
  • 1
  • 1
Kevin Nelson
  • 7,613
  • 4
  • 31
  • 42
  • The overflow of the outer div comes from when the outer div's width is x, but the outer div's height is smaller than 9x/16. Thus the inner div's height is 9x/16, which is larger than the desired max height of the inner div. Edit: Oops, pressed enter too soon. With your sample, I noticed that the height of the outer div increases as I expand the window horizontally. The height of the outer div should be constant. – Valka Jul 06 '15 at 22:10
  • @Valka, new codepen added at the bottom. If this still doesn't work, you really do need to create a codepen yourself. Fork mine or create your own to recreate the problem...otherwise, I'm firing in the dark as to what the actual problem is. A CodePen example that people can fork, tweak, and fix cuts our time investment down to a few minutes and makes it much more likely that you'll get good answers to your problems without a lot of wasted back and forth. – Kevin Nelson Jul 06 '15 at 23:11
  • Thanks for the revision. From your updated CodePen example, it behaves as I'd like. I've incorporated your example into my test code, but am still working out some kinks. The inner
    doesn't stop at a certain height (in mine), so I'll try to show you what I've written. Is jsfiddle ok for you?
    – Valka Jul 06 '15 at 23:33
  • Here's a skeleton of the layout. The blue box is where the 16:9 ratio is kept and it should just touch the yellow bar below it. I can't seem to get the box to stay in place. (I did not hard code a height for the outer
    though) https://jsfiddle.net/valka/6wrk4xp3/6/
    – Valka Jul 06 '15 at 23:51
  • @Valka, updated my CodePen to match your layout: http://codepen.io/anon/pen/XbEebm – Kevin Nelson Jul 07 '15 at 15:53
  • Kevin, from your CodePen, when I expand the window horizontally, the box div expands with the height, but the height doesn't stop expanding after a certain point, so the box div takes over most of the screen the wider my browser is. Your previous update had the ideal behavior, but it's no longer the same in the latest update. I don't know if you see that in your browser as well. Edit: pressed enter too soon again... thank you for your help though! I really appreciate it :) – Valka Jul 07 '15 at 17:28
  • @Valka, Just add a max-width and max-height to the #outer-wrapper. Set the max-height to whatever you want the largest height to be, then take out a calculator and do ((max-height/9)*16) to get what your max-width should be in correlation to that max-height. – Kevin Nelson Jul 07 '15 at 18:24