Valka
Valka

Reputation: 33

Keep div aspect ratio within another div

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;
}

Upvotes: 3

Views: 3427

Answers (2)

Kevin Nelson
Kevin Nelson

Reputation: 7673

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.

Upvotes: 0

Yandy_Viera
Yandy_Viera

Reputation: 4380

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

Upvotes: 1

Related Questions