how to make nested flexboxes work

2020-02-09 00:27发布

I have a small example of a nested flexbox setup: http://jsfiddle.net/ThomasSpiessens/MUrPj/12/

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

In this example the following applies:

  • CSS 'box' classes use flexbox properties on which only the boxContent is told to grow. For specific CSS properties and values, please check the fiddle.
  • 'fullSize' just sets both width and height to 100%.

When you check this fiddle with Firefox and Chrome you get different results. In Firefox it does what I would suppose it has to do, which is stretching the inner .boxContent. In Chrome however, the inner .boxContent doesn't get stretched.

Would anyone have an idea how to make the content stretch in Chrome as well ? perhaps a specific webkit property that is missing ?

4条回答
Evening l夕情丶
2楼-- · 2020-02-09 00:58

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>
查看更多
放荡不羁爱自由
3楼-- · 2020-02-09 01:00

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.

查看更多
▲ chillily
4楼-- · 2020-02-09 01:08

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

查看更多
Root(大扎)
5楼-- · 2020-02-09 01:13

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;
}
查看更多
登录 后发表回答