Dmitry Avtonomov
Dmitry Avtonomov

Reputation: 9489

auto adjust container <DIV> height to accommodate absolutely positioned child <DIV>s

is there a way to auto adjust container DIV height to accommodate absolutely positioned child DIVs? i'd like to get something like

+-----------------------+
| container             |
|  +------+   +------+  |
|  | chld |   | chld |  |
|  |   1  |   |   2  |  |
|  |      |   |      |  |
|  +------+   +------+  |
|       +------+        |
|       | chld |        |
|       |   3  |        |
|       |      |        |
|       +------+        |
+-----------------------+

i try something like:

<div class="container" style="position: relative; border: solid thin">
    <div class="chld" style="width: 20px; 
                             height: 20px; 
                             position: absolute; left: 5px; top: 5px;
                             border: dashed thin;"><div>
    <div class="chld" style="width: 20px; 
                             height: 20px; 
                             position: absolute; left: 30px; top: 5px;
                             border: dashed thin;"><div>
    <div class="chld" style="width: 20px; 
                             height: 20px; 
                             position: absolute; left: 15px; top: 30px;
                             border: dashed thin;"></div>
</div>

but the "container" div stays zero height. I understand, that this might be the expected behaviour, as elements are 'taken out' of the flow when positioned absolutely, but is there a workaround for this? (except for precalculating the resulting height and setting it manually)

Upvotes: 30

Views: 65052

Answers (7)

wheresrhys
wheresrhys

Reputation: 23500

If you use position:relative instead of position absolute an empty space will stay in the page structure where the element should be, and this space will be the height of the element you've moved.

So you could float chld1 and chld2 to get them side by side, add top & bottom padding to push chld 3 down and use position relative to split them apart and move to any height. Then use clear both on chld3.

Something like

#exp_outer {
  width: 400px;
  border: 1px solid black;
}
#chld1 {
  float: left;
  margin: 30px 0 20px;
  left: 50px
}
#chld2 {
  float: right;
  margin: 30px 0 20px;
  right: 50px;
}
#chld3 {
  left: 150px;
  clear: both;
}
.box {
  position: relative;
  width: 80px;
  height: 80px;
  border: 1px solid black;
}
<div id="exp_outer">
  <div id="chld1" class="box">Child1</div>
  <div id="chld2" class="box">Child2</div>
  <div id="chld3" class="box">Child3</div>
</div>

Upvotes: 9

Konrad Gałęzowski
Konrad Gałęzowski

Reputation: 1983

I couldn't find any simple pure-javascript workaround for this little problem, so here it comes (you need to add id fields to your html code):

var containerBox = document.getElementById('container');
var statBoxBottom = document.getElementById('chld3').getBoundingClientRect().bottom + window.scrollY;
var mainDivBottom = containerBox.getBoundingClientRect().bottom + window.scrollY;
var boxHeightDiff = statBoxBottom - mainDivBottom;
if (boxHeightDiff > 0) 
    containerBox.style.height = Math.ceil( containerBox.offsetHeight + boxHeightDiff ) + 'px';

It basically increases "container" height based on absolute bottom position of "chld3".

Upvotes: 0

Nicola
Nicola

Reputation: 364

I've troubled quite a lot to achieve this and now that i have a solution it looks like it would have been so simple, anyway, some jQuery/Javascript is needed:

jQuery(window).load(function(){
    var valueCheck = [];
    jQuery('.projectsWrap .hentry').each(function(){
        var itemObj = jQuery(this);
        var itemValues = itemObj.position();
        var top = itemValues.top;
        var height = jQuery(this).height();
        var sum = top + height;
        valueCheck.push(sum);
    });
    var res = Math.max.apply(Math, valueCheck);
    jQuery('.projectsWrap').height(res);
});

I wrote and implemented this little script in a WordPress theme hence you see the "$" are converted to "jQuery" for compatibility but if you are not using WordPress you should revert them back to "$".

The situation i was in was even more difficult than the one in the question because the user wanted to autonomously absolutely position each element in the container and the order in which elements appeared in the dom was not related to their position in the container: totally unexpectable results (first element in the dom may appear as last bottom element in the window for example).

Also the heights of elements were all different, all different heights and all different top values (offset), a nightmare.

What the script does is get the height and top value of each element, sum them and put this sum in an array, the array is then checked to find the biggest value, this value is the height the container will be set to, magic!

Upvotes: 0

Ahmad Bagadood
Ahmad Bagadood

Reputation: 124

overflow:auto

This is the new clearfix method, FYI. However, it doesn't always expand the container to the height of its tallest & absolutely positioned child.

Upvotes: 10

Dmitry Avtonomov
Dmitry Avtonomov

Reputation: 9489

i ended up using clearfix, this allows me to set the desired width of the container, and it's height will be adjusted automatically, depending on the contents (this works in all browsers)

<style>
        .inner_box {
            position: relative;
            float: left;
            width: 50px; 
            height: 50px; 
            border: dashed thin;
            margin: 5px 5px 5px;
            text-align: center;
        }

        .outer_box {
            position: relative; 
            top: 200px;
            border: solid thin; 
            width: 190px;
            //height: 1%;
        }

        .outer_box:after {
            content: '.'; 
            display: block; 
            clear: both; 
            visibility: hidden; 
            height: 0; 
            line-height: 0;
        }
    </style>

<div class="outer_box">
    <div class="inner_box">1</div>
    <div class="inner_box">2</div>
    <div class="inner_box">3</div>
    <div class="inner_box">4</div>
    <div class="inner_box">5</div>
    <div class="inner_box">6</div>
</div>

Upvotes: 4

buti-oxa
buti-oxa

Reputation: 11431

No. The whole idea is that absolutely positioned element does not influence its parent layout.

Try achieving your goal by relatively positioning floats instead of absolute positioning of divs. It is not as convenient (because of starting position of your floats is not ass 0,0) but it will work.

Upvotes: 2

wiebersk
wiebersk

Reputation: 23

If you give the .container div a height of 100% it should calculate it from the child elements in most browsers but unfortunately not IE6 or lower.

Upvotes: -6

Related Questions