How do I make flexbox objects correct when in a nested container?
If I set up a nested flexbox container like this:
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2"></div>
</div>
</div>
</div>
... and then set the width of grow2 to be wider than container1 and then2 overflows container1.
I believe this should not be happening as flex items should shrink when they are larger than the flex container.
If I set flex-basis of grow2, then it works as expected.
For a demonstration, see the following example:
https://jsfiddle.net/chris00/ot1gjjtk/20/
Use Chrome or Firefox for this
Also, I've read that the flexbox spec says that width and flex-basis should have the same effect (when using horizontal layouts) that they clearly don't.
Now I could just use flex-base instead of width, but ... Edge does the same for both flex-base and width, and does it "wrong". IE11 does it wrong (although there seem to be a few flexbox bugs). Please check out the demo with Edge.
So how is this supposed to work?
Are there bugs in all browsers?
Is flex-basis actually different from width (in simple horizontal layouts)?
Or is Edge correct, and both width and flex-basis should overflow the parent container?
Finally, is there a workaround that can fix the overflow for Edge (and even IE11)?
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
source to share
Problem
As for the specifications relating to this is not a problem flex-basis
, width
, flex-grow
or flex
. This is something completely different.
4.5. Assumes minimum size Flex Items
To provide a more reasonable default minimum size for flex items, this specification introduces a new value
auto
as the initial property valuemin-width
andmin-height
is defined in CSS 2.1.
In other words, a flex item by default cannot be less than the length of its content (essentially the longest word or fixed-size item).
An element cannot stay in its container (or even display a scrollbar or ellipsis) because its content is not allowed to overflow. The content just expands the element. This also applies to fixed size (like flex-basis: 400px
in your code).
Initial settings again:
-
min-width: auto
, in line-direction -
min-height: auto
, in the direction of the column
For a more complete explanation see this post:
Solution for Chrome, Safari, Firefox and Edge
The standard solution to this problem is simple: override the default.
In your code, add min-width: 0
to .grow1
.
This fixes the issue in Chrome, Safari, FF and Edge.
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
min-width: 0; /* NEW */
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
Solution for IE11
In IE11, contrary to what the spec says, the defaults are min-width
/ min-height
narrower 0
, but the flex item still fails.
The defaults 0
are because when the flexbox spec was first released, the properties min-*
did not deviate from the initial CSS 2.1 values that 0
.
Later, after the browsers finished their implementations, the flex values min-*
were updated to auto
. Chrome, Safari, FF and Edge update. IE11 didn't.
The reason flex items are coming out in IE11 is due to another issue: the browser wants to get the explicit width in the container
In your code, add flex-basis: 100%
to .grow1
.
More details here:
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
flex-basis: 100%; /* NEW */
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
More browser discrepancies
Evidence exists (in this question and other examples I've seen) that Webkit-based browsers no longer abide by the standard value auto
given in the spec.
In addition, compliance with the standard auto
may vary depending on which property is used for calibration: flex-basis
vs. width
/height
As discussed in the next post, these properties should display the same.
source to share