Skip to content Skip to sidebar Skip to footer

Nested Flexboxes Works Differently Across Browsers

I have a small example of a nested flexbox setup: http://jsfiddle.net/ThomasSpiessens/MUrPj/12/ In this example the following applies: CSS 'box' classes use flexbox properties o

Solution 1:

Unless you need that extra div, remove it. There is sometimes a difference between the height of an element and its length along the main axis (column orientation), which is causing some confusion here. Basically, it looks like it is taller than the browser believes it to be, which is why height: 100% doesn't work like you expect (I'm not certain which behavior is correct in this instance).

For whatever reason, promoting the element to a flex container works.

http://jsfiddle.net/MUrPj/14/

<div class="box fullSize">
    <div class="boxHeader">HEADER</div>
    <div class="boxContent box">
        <div class="boxHeader moregreen">INNER HEADER</div>
        <div class="boxContent red">CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT</div>
        <div class="boxFooter moreblue">INNER FOOTER</div>
    </div>
    <div class="boxFooter">FOOTER</div>
</div>

Solution 2:

This question has been linked for a specific problem: How to make nested elements in a flex box fill the whole height? The short answer is:

Use display:flex on the child and avoid height:100%. Here is a simplified example on codepen.

CourtDemone explained it well (more here):

According to the flexbox spec, an align-self:stretch value (the default for a flex'd element) changes only the used value of an element's cross-size property (in this case, height). Percentages however are calculated from the specified value of the parent's cross-size property, not it's used value.


Solution 3:

I've found a solution without removing the extra-div.

You need to make boxContent relative positioned and its containing box absolute.

With attaching an extra css class to the inner div:

<div class="boxContent">
    <div class="box fullSize innerBox">

and following css:

.boxContent {
  ...
    position: relative;
}
.innerBox{
    position: absolute;
    top: 0px;
    bottom: 0px;
}

here's the updated jsfiddle: http://jsfiddle.net/MUrPj/223/

This question is pretty old, but this might be helpful for future visitors


Solution 4:

This JsFiddle is the minimum needed CSS attributes to get nested flexboxes to work. I've shown it for column; if you are doing this within a row, remove the two "flex-direction: column"s. [In this trivial example, removing those won't change anything, because there is only one child of each flexbox. But as soon as you add a second child, you'll be working in either a row or a column.]

HTML:

<div id="e1">
  <div id="e2">
    <div id="e3">    
    </div>
  </div>
</div>

CSS:

html, body, #e1 {
  height: 100%; width: 100%;
}
#e1 {
  background-color: #ff0000;
  display: flex;
  flex-direction: column;
}
#e2 {
  background-color: #ffff00;
  /* Won't work if remove either of the next 2 lines - a box collapses. */
  flex: 1;
  display: flex;
  flex-direction: column;
}
#e3 {
  background-color: #00ff00;
  flex: 1;
}

In my experience, Safari 13 (both MacOS and iOS) is more finicky (re nested flex items) than Chrome 77, Firefox 69, or even Edge 18.
While in this simple example, all 3 react the same, I had a more complex situation which worked in all but Safari. Nevertheless, the code shown here -- especially the two lines in #e2 after "Won't work if remove either of the next 2 lines" -- is the essence of what made my more complex situation work in Safari.

In addition, if having difficulties, first step is to remove all "percent" height attributes within the nested elements. Here, that means #e1 is permitted to have height: 100% - this is within the context of its parent, which is not a flex container. But #e2 and #e3 should not declare % heights.

Having nested elements with heights that are not relative to their parent (pixels, ems, vh) are fine, AFAIK. Note that vh works, because it is relative to window size, which isn't affected by the nested flex containers' (#e1, #e2) heights. So that calculation logic is easy for browser to get right.


As requested, example of nesting four deep. Uses class names to make it easier.

HTML:

<div class="fb-outer">
  <div class="fb-middle">
    <div class="fb-middle">
      <div class="fb-inner">    
      </div>
    </div>
  </div>
</div>

CSS:

html, body, .fb-outer {
  height: 100%; width: 100%;
}
.fb-outer {
  background-color: #ff0000;
  display: flex;
  flex-direction: column;
}
.fb-middle {
  background-color: #ffff00;
  /* Won't work if remove either of the next 2 lines. */
  flex: 1;
  display: flex;
  flex-direction: column;
}
.fb-inner {
  background-color: #00ff00;
  flex: 1;
}

Solution 5:

*,*::before,*::after {
margin:0;
padding:0;
box-sizing:border-box;

}
body {
width:100%;
height:100vh;
background-color:purple;
}

.fullSize {
   width: 100%;
   height: 100%; 
    margin: 0;
    padding: 0;
 
}



.box {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -ms-flex-direction: column;
  -webkit-flex-direction: column;
  flex-direction: column;
  background-color: brown;
}

/* line 7, ../../app/styles/_layout.scss */
.boxHeader {
background-color: green;
}

/* line 12, ../../app/styles/_layout.scss */
.boxContent {
  -ms-flex: 1 0 auto;
  -webkit-flex: 1 0 auto;
  flex: 1 0 auto;
  -webkit-box-flex: 1.0;
  background-color: yellow;
}

/* line 18, ../../app/styles/_layout.scss */
.boxFooter {
  background-color: cornflowerblue;
}

.moreblue {
    background-color: blue;
}

.moregreen {
    background-color: darkgreen;
}

.red {
    background-color: red;
}
<div class="box fullSize">
    <div class="boxHeader">HEADER</div>
    <div class="boxContent">
            <div class="box">
                <div class="boxHeader moregreen">INNER HEADER</div>
                <div class="boxContent red">
                     CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT  
                </div>
                <div class="boxFooter moreblue">INNER FOOTER</div>
            </div>
        </div>
    <div class="boxFooter">FOOTER</div>
</div>

Post a Comment for "Nested Flexboxes Works Differently Across Browsers"