76

I have designed a 100% width 100% height layout with css3 flexbox, which works both on IE11 (and probably on IE10 if emulation of IE11 is correct).

But Firefox (35.0.1), overflow-y is not working. As you can see in this codepen : http://codepen.io/anon/pen/NPYVga

firefox is not rendering overflow correctly. It shows one scrollbar

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
}
.level-0-container {
  height: 100%;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column; 
}
.level-0-row1 {
  border: 1px solid black;
  box-sizing: border-box;
}
.level-0-row2 {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  border: 1px solid black;
  box-sizing: border-box;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
}
.level-1-col1 {
  width: 20em;
  overflow-y: auto;
}
.level-1-col2 {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  border: 4px solid blue;
  box-sizing: border-box;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
}
.level-2-row2 {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  border: 4px solid red;
  box-sizing: border-box;
  overflow-y: auto;
}
<html>
<body>

    <div class="level-0-container">

        <div class="level-0-row1">
            Header text
        </div>

        <div class="level-0-row2">

            <div class="level-1-col1">
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                line <br/>
                
            </div>

            <div class="level-1-col2">

                    <div class="level-2-row1">
                        Some text
                        <p/> Some text 2
                        <p/> Some text 3
                        <p/> 
                    </div>

                    <div class="level-2-row2">
                        <p>some text</p>
                        <p>some text</p> 
                        <p>some text</p> 
                        <p>some text</p>
                        <p>some text</p>
                        <p>some test</p>
                    </div> 
                </div>

        </div>

    </div>
</body>


</html>
rekna
  • 5,313
  • 7
  • 45
  • 54

2 Answers2

186

tl;dr: you need min-height:0 in your .level-0-row2 rule. (Here's a codepen with that fix.)

More detailed explanation:

Flex items establish a default minimum size that's based on their children's intrinsic size (which doesn't consider "overflow" properties on their children/descendants).

Whenever you've got an element with overflow: [hidden|scroll|auto] inside of a flex item, you need to give its ancestor flex item min-width:0 (in a horizontal flex container) or min-height:0 (in a vertical flex container), to disable this min-sizing behavior, or else the flex item will refuse to shrink smaller than the child's min-content size.

See https://bugzilla.mozilla.org/show_bug.cgi?id=1043520 for more examples of sites that have been bitten by this. (Note that this is just a metabug to track sites that were broken by this sort of issue, after this spec-text was implemented -- it's not actually a bug in Firefox.)

You won't see this in Chrome (at least, not as of this posting) because they haven't implemented this minimum sizing behavior yet. (EDIT: Chrome has now implemented this min-sizing behavior, but they may still incorrectly collapse min-sizes to 0 in some cases.)

dholbert
  • 11,386
  • 3
  • 42
  • 31
  • 3
    I've hit this issue but I had to add min-height:0 to all the parent flexbox columns - any idea why? – Ambroz Bizjak Jun 11 '16 at 13:22
  • 1
    Does this min-height (in my case) need to be applied to *every* ancestor? Or just the immediate parent? – Sam Storie Jun 14 '16 at 21:12
  • 6
    It potentially needs to be applied to every ancestor that is a flex item (i.e. every ancestor whose parent is `display:flex`), depending on the circumstances. – dholbert Jul 05 '16 at 17:58
  • Are there any plans to change the spec to take overflow into account? Now that I know why this happens I can work around it, but it will still be annoying. – trysis Dec 30 '16 at 20:32
  • RE spec changes -- I asked about this on the CSS working group list, and the spec editor replied that "we don't think it's possible to address this in any sane way" (and I agree, given the primitives that CSS has to work with). https://lists.w3.org/Archives/Public/www-style/2014Aug/0282.html So you'll likely continue to need `min-width:0` / `min-height:0` hackarounds for situations like this, going forward. – dholbert Jan 03 '17 at 22:06
  • 1
    Any reason we can't just apply `* { min-height: 0; min-width: 0; }`? – Brett Jan 28 '17 at 03:50
  • You could do that, but that would disable the Good Things that the magic `min-width:auto` behavior brings. In particular: flex items are set up to be shrinkable down to their resolved `min-width` (or `min-height` if vertical) by default, by virtue of having `flex-shrink:1` in their initial style. So if you set `min-width` (or `min-height`) to 0, then your flex items will let themselves *shrink down to 0* by default, which might not be what you want -- particularly if it's just because another greedy flex item is stealing all of the space. – dholbert Feb 03 '17 at 22:43
  • 4
    @Brett, here's a jsfiddle demonstrating the sort of badness (content overflowing/overlapping) that can arise from using `min-width:0` too aggressively: https://jsfiddle.net/85scnr1b/ So really, you only want to add `min-width:0` on flex items whose content can "behave nicely" if it's given an arbitrarily-smaller `width` than it expects. (Same goes for `min-height` & `height`, for vertical flex containers.) – dholbert Feb 03 '17 at 22:48
  • In my case even setting min-height on all ancestors is not working. I have to compute the height at runtime using window.getComputedStyle & calculate the height that can be taken by the scrollable area. I'm using chrome. Any reason why this might be the case? – Ashok Koyi Jun 28 '17 at 13:31
  • For whatever reason adding min-height:0px to my parent flex item resolved this issue for me, setting it on child-ancestors appeared to have no affect. Issue was only occurring in FF. – Boog Dec 18 '17 at 23:19
0

Recently I have found a better solution:

Instead of using:

flex:1 1 auto;
min-height: 0;

it's even better to use:

flex:1 1 0;

Basically this tells the browser to set the size of the element initially to 0 (so replacing min-height) and allow it to expand by a ratio of 1.

There is a really good video for explaining how flexbox works by Kevin Powell which I highly recommend to watch (https://www.youtube.com/watch?v=fm3dSg4cxRI) It explains in detail how flexbox algoritm works.

rekna
  • 5,313
  • 7
  • 45
  • 54