6

I'm trying to nest a flexbox in another flexbox. The outer box is vertical:

+------+
|      |
+------+
|      |
|      |
|      |
+------+

Where the top area fits the content flex 0 1 auto and the bottom half fills the remaining space flex 1 1 auto.

In the bottom half I have another flex-box going horizontal. I want the 2 inner boxes to be space-between across and flex-end for align-items so basically the 2 inners are pinned to the left and right bottom corners like this:

+------+
|      |
+-+  +-|
|L|  |R|
+------+

Setting this up seems to work in Firefox but in Chrome(Blink) and Safari I get this:

+------+
|      |
|      |
|      |
+-+--+-|
|L|  |R|
+-+  +-+

Here's the HTML

<div id="outer">
    <div id="top">
        top
    </div>
    <div id="bottom">
        <div id="bottomcontents">
            <div id="botleft">
                bottom left
            </div>
            <div id="botright">
                bottom right
            </div>
        </div>
    </div>
</div>

And there's the CSS

* {
    box-sizing: border-box;
    -moz-box-sizing: border-box;   
}

html, body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
    border: 0px;
}

#outer {
    height: 100%;
    border: 1px solid red;
    display: flex;
    display: -webkit-flex;
    flex-flow: column;
    -webkit-flex-flow: column;
    justify-content: center;
    align-content: center;
    align-items: center;
    -webkit-justify-content: center;
    -webkit-align-content: center;
    -webkit-align-items: center;
    min-height: auto;    
}
#top {
    width: 100%;
    flex: 0 1 auto;
    -webkit-flex: 0 1 auto;
    border: 1px solid blue;
}
#bottom {
    width: 100%;
    height: 100%;
    flex: 1 1 auto;
    -webkit-flex: 1 1 auto;
    border: 1px solid green;
}
#bottomcontents {
    height: 100%;
    width: 100%;
    border: 1px solid pink;
    display: flex;
    display: -webkit-flex;
    flex-flow: row;
    -webkit-flex-flow: row;
    justify-content: space-between;
    align-content: center;
    align-items: flex-end;
    -webkit-justify-content: space-between;
    -webkit-align-content: center;
    -webkit-align-items: flex-end;
    min-height: auto;        
}

#botleft, #botright {
    flex: 0 1 auto;
    -webkit-flex: 0 1 auto;
}
#botleft {
    border: 1px solid purple;
}
#botright {
    border: 1px solid cyan;
}

And here's a fiddle

It works as expected in Firefox. Did I do something wrong? Is this a bug in Chrome and Safari? Is there a workaround?

Icarus
  • 1,627
  • 7
  • 18
  • 32
gman
  • 100,619
  • 31
  • 269
  • 393

1 Answers1

3

Basicaly, what you're seeing is that the "height: 100%;" on #bottomcontents is forcing the container "outside" of its surrounding container. The 100% height ends up getting its height from its parent, which also has 100% height; meaning that the height being specified for #bottomcontents is being set to the same height as #outer. You can see a little more clearly that it's going beyond what it should if you add "overflow: hidden;" to #bottom. A more in-depth discussion of your issue can be found here: you're running into is covered here: Height 100% on flexbox column child

Unless I am missing some requirement you're needing, you can also remove the #bottomcontents container and make due just with #bottom. Example code (jsfiddle example at the bottom):

HTML:

<div id="outer">
    <div id="top">
        top
    </div>
    <div id="bottom">
        <div id="bottomcontents">
            <div id="botleft">
                bottom left
            </div>
            <div id="botright">
                bottom right
            </div>
        </div>
    </div>
</div>

CSS:

* {
    box-sizing: border-box;
    -moz-box-sizing: border-box;   
}

html, body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
    border: 0px;
}

#outer {
    border: 5px solid red;
    display: flex;
    display: -webkit-flex;
    height: 100%;
    width: 100%;
    flex-direction: column;
    -webkit-flex-direction: column;
}

#top {
    width: 100%;
    border: 5px solid blue;
    flex: 0 1 auto;
    -webkit-flex: 0 1 auto;
}

#bottom {
    width: 100%;
    display: flex;
    display: -webkit-flex;
    flex-direction: row;
    -webkit-flex-direction: row;
    justify-content: space-between;
    -webkit-justify-content: space-between;
    height: 100%;
    border: 5px solid green;
    align-items: flex-end;
    -webkit-align-items: flex-end;
}

#left {
    border: 5px solid purple;
    padding: .5em;
    flex: 0 1 auto;
    -webkit-flex: 0 1 auto;
}

#right {
    border: 5px solid cyan;
    padding: .5em;
    flex: 0 1 auto;
    -webkit-flex: 0 1 auto;
}

My fiddle: http://jsfiddle.net/blake770/2br5x/

Community
  • 1
  • 1
  • Hrm. This seems really wrong (I'm not saying you're wrong, I'm saying I don't understand the rational). In my example `#bottom` fills whatever is leftover from `#outer` once `#top` takes up whatever space it needs. If I put anything inside `#bottom` and I want it to fill up the space in `#bottom` then I would need to say `height: 100%` to tell it "be 100% the size of your parent" which is `#bottom`. Your example works at the expense of getting rid of `#bottomcontents` but what if I need `#bottomconents`? I read the answer you linked to, I just don't get how flex is useful as specced. – gman Apr 17 '14 at 08:30
  • 1
    There are a couple ideas you can play with, here's a fiddle of one as an example: http://jsfiddle.net/blake770/2br5x/1/. I added a "#content" div between #top and #bottom, and set the height of the bottom to 0. This may allow you to give a little more separation between header/content/footer than throwing things in #bottomcontents. Setting the height of #bottom to 0 still shows the right and left columns, but it allows the stuff in contents to still "reach" the bottom. You can also add a div between #left and #right and place content there, but that will mean you'll have a margin on each side. – Carl Blakemore Apr 17 '14 at 20:16