1

On Chrome I encountered Flexbox behaviour I don't understand. When a flex child which is also a flex container has flex: 1 0 0px, it collapses itself and it's contents.

Even though flex-basis is set to 0px, as far as I understand setting flex-grow to 1 (first number in flex shorthand) should make the item grow, when needed.

In my example .bottom-container has height set to 300px. That height is respected on Firefox, but collapsed to 0px on Chrome. Why?

.top-container {
  display: flex;
  flex-flow: column nowrap;
}

.middle-container {
  flex: 1 0 0px;
  display: flex;
  flex-flow: column nowrap;
}

.bottom-container {
  flex: 0 0 auto;
  height: 300px;
}
<div class="top-container">
  <div class="middle-container">
    <div class="bottom-container"></div>
  </div>
  <div class="middle-container">
    <div class="bottom-container"></div>
  </div>
</div>
Robert Kusznier
  • 6,471
  • 9
  • 50
  • 71
  • 3
    `Flex: 1 0 0 ;` tells `flex-basis:0;`, i would say, chrome has the right behavior :( – G-Cyrillus Oct 31 '17 at 16:44
  • @G-Cyr: But doesn't set `flex-grow: 1` should make the item growable when needed? Sometimes I need to set `flex-basis: 0` to make sure all flex children have exactly the same size. – Robert Kusznier Oct 31 '17 at 16:46
  • it is not coherent, sizing it to zero and allow it to grow at the same time, use auto for the flex-basis value, then each flex setting works as expected ;) It is like : width:0; max-width:100%; there is a conflict in the logic – G-Cyrillus Oct 31 '17 at 16:48
  • @G-Cyr: Yeah, definitely `flex: 1 0 0` is not clear declaration of what it wants to accomplish. But it's a valid declaration - the basis size is 0px and then grow to use all remaining space - and I don't understand why it doesn't work. – Robert Kusznier Oct 31 '17 at 16:54
  • There is no guidance in the flexbox spec about how browsers should interpret different units on `flex-basis` values. I wouldn't recommend a unitless value even though you are correct, it is a valid declaration. – Michael Benjamin Oct 31 '17 at 17:00
  • I did not mention it was not valid, but not coherent (clear). This is a young spec and you can expect for a while to see different interpretation from a browser engine to another one . *IE6 told me long time ago to be as much as specific as possible to avoid unexpected behavior (and avoid totally the buggy ones)*. If it is not working, it might have been to do with the way it is implemented, and flex-basis overides the flex grow value here .... it should be fine somedays , obviously not yet ;) . Advice IMHO : **avoid it** at this time – G-Cyrillus Oct 31 '17 at 17:09
  • @G-Cyr: I didn't think unitless `0` makes any different. I re-phrased the question to have `0px` instead of `0` - the effect is the same. – Robert Kusznier Oct 31 '17 at 17:23
  • @G-Cyr, my last comment was to Robert, in case you think it was a response to your comment. – Michael Benjamin Oct 31 '17 at 17:33
  • Sorry, it looks like i made things more confused to you. Mickael_B answers gives you an approach to follow, ;) – G-Cyrillus Oct 31 '17 at 17:33
  • @Robert, unitless `flex-basis` values make a BIG difference, especially in IE. See the third bullet point in my answer here: https://stackoverflow.com/q/32239549/3597276 – Michael Benjamin Oct 31 '17 at 17:34
  • @G-Cyr: And about coherency: what is the clearest way to describe the following layout with Flexbox: all flex children should be of the same size, no matter what size are their contents. So far I've been using `flex: 1 0 0` for that. – Robert Kusznier Oct 31 '17 at 18:14
  • When i wish to spray evenly flex children on a col or a row, i use flex:1; on its own. just because too much flex kills flex. ;) The way i see it , when i use 0, it is to mean 0, no matter the units, and as said, % size needs a parent with a size set to be calculated, else it is much alike % of null. Flex is a usefull grid system, so is the table-layout and the CSS grid too, but none are magic :( . My english is not good enough to go in detailled & subtil discussion how flex:1 0 0 ; should behave, be usedwhen, why. CSS is very flexible and breaks easily. it's a virtual world of compromis ;) – G-Cyrillus Oct 31 '17 at 18:32

2 Answers2

1

The problem is with the flex-basis component.

When you have flex-basis: 0, Chrome and Firefox compute to flex-basis: 0px.

However, the pixel value breaks your layout in Chrome.

Instead, for cross-browser compatibility, use this:

flex: 1 0 0%
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • The part I don't understand is why `px` value breaks the layout in Chrome? – Robert Kusznier Oct 31 '17 at 16:52
  • 1
    It's how Chrome renders `px` vs `%` units. Forget about `flex-basis` for a minute. Use `height` instead. Same thing. https://codepen.io/anon/pen/ooXEvO – Michael Benjamin Oct 31 '17 at 16:55
  • There is a history of Chrome / Safari and Firefox rendering heights differently, especially in flex containers. https://stackoverflow.com/q/33636796/3597276 – Michael Benjamin Oct 31 '17 at 16:57
  • @Michael_B - that would essentially be the same as saying `flex: 1 0 auto` because `0%` height is not computable because the parent has no height (and it's layout is columnar). That, and `flex: 1 0 auto` makes a lot more sense from a readability perspective than `flex: 1 0 0%`. – Adam Jenkins Oct 31 '17 at 16:58
  • That's not necessarily correct. Some (maybe most) major browsers now use the computed height on the parent to determine the percentage height on the child. See the link I just posted above. – Michael Benjamin Oct 31 '17 at 17:02
  • @Michael_B: I see your solution works, but I still don't understand why. The post you linked (https://stackoverflow.com/q/33636796/3597276) explains why setting `height` value in percentages on a child isn't valid until the parent has explicitly `height` too. Then why setting `flex-basis: 0%` fixes the problem in Chrome? The parent hasn't height set explicitly, so `0%` shouldn't make sense. – Robert Kusznier Oct 31 '17 at 17:02
  • See the last two paragraphs before the "Solutions" section. – Michael Benjamin Oct 31 '17 at 17:02
  • 1
    @Michael_B: Okay, I see it, thanks. Now I'm trying to get my head around it :). – Robert Kusznier Oct 31 '17 at 17:05
  • @Michael_B: Sorry, but I still don't understand it fully. When I set `flex-basis: 0%`, judging from what you said in the other post - "Chrome looks to the parent (.item) for reference and responds: 100% of what? I don't see anything (ignoring the flex: 1 rule that is there). As a result, it applies height: auto (content height), in accordance with the spec." - Chome calculates this to `flex-basis: auto`. But setting `flex-basis: auto` produces a little different effect in Chrome than `flex-basis: 0%`. Why? – Robert Kusznier Oct 31 '17 at 18:10
  • The overall point is that browsers vary in their rendering behavior, especially when the spec language is unclear. There is no definite guidance in the spec (as far as I could tell) for what browser makers should do with `flex-basis` values that are percentages, pixels or unitless. If there was, you would likely find consistent behavior in both FF and Chrome. – Michael Benjamin Oct 31 '17 at 18:15
  • Instead, you find that unitless values are rendered differently in FF, Chrome, IE, Edge and Safari. They're all over the map. Hence, my recommendation in a previous comment, that you veer away from unitless values. And, test, test, test. – Michael Benjamin Oct 31 '17 at 18:17
  • I understand why I should stay away from unitless values, but I do not understand why `flex-basis: 0%` is any different from `flex-basis: auto` (I tested and it is). From what you said Chrome should interpret `0%` as `auto` when parent does not have explicitly set `height`. – Robert Kusznier Oct 31 '17 at 18:19
  • 1
    I also said that browsers are evolving from that traditional interpretation of the spec and taking other forms of height into consideration. I can count at least 6 differences right-off-the bat in flex rendering behavior between Chrome and FF. [Chrome even goes completely off-spec once in a while.](https://stackoverflow.com/q/36247140/3597276) Why, you ask? I can only guess. – Michael Benjamin Oct 31 '17 at 18:26
0

Ok, so here's the logic.

You haven't specified a height of .top-container so it's child elements (.middle-container) cannot grow, because there is no room for them to grow into, despite having flex: 1 0 0 and, therefore, .middle-container elements will always maintain a height of 0.

Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100