If I set up a nested flexbox container like so:
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2"></div>
</div>
</div>
</div>
...and then set the width of grow2 such that it is wider than container1 then grow2 overflows container1.
I believe this should not happen since flex elements are supposed to shrink when they are larger than the flex container.
If I set the flex-basis of grow2 then this works as expected.
Please see the following example for a demo:
https://jsfiddle.net/chris00/ot1gjjtk/20/
Please use Chrome or Firefox for this
Furthermore, I read that the flexbox spec says that width and flex-basis should have the same effect (when using horizontal layouts) which they clearly don't.
Now I could just use flex-basis instead of width, but... Edge does the same thing for both flex-basis and width, and it does it in the "wrong" way. IE11 does it wrong also (although that appears to have multiple 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 supposed to be different from width (in simple horizontal layouts)?
Or is Edge correct and both width and flex-basis are supposed to 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>
The flex-shrink CSS property sets the flex shrink factor of a flex item. If the size of all flex items is larger than the flex container, items shrink to fit according to flex-shrink .
By default, the child elements of a flexbox container will stretch vertically to fill the height of the container. This can be prevented by using the align-self property on the child element that you do not want to stretch.
A flexbox item can be set to a fixed width by setting 3 CSS properties — flex-basis, flex-grow & flex-shrink. flex-basis : This property specifies the initial length of the flex item. flex-grow : This property specifies how much the flex item will grow relative to the rest of the flex items.
Here's the solution: When the screen resizes smaller than 990px, allow flex items to wrap and give the first item a 100% width, which forces the following items to the next line.
As far as the spec is concerned, this isn't an issue pertaining to flex-basis
, width
, flex-grow
or flex
. It's something entirely different.
4.5. Implied Minimum Size of Flex Items
To provide a more reasonable default minimum size for flex items, this specification introduces a new
auto
value as the initial value of themin-width
andmin-height
properties defined in CSS 2.1.
In other words, a flex item, by default, cannot be smaller than the length of its content (essentially, the longest word or fixed-size element).
The item cannot stay within its container (or even render a scroll bar or ellipsis), because its content is not permitted to overflow. The content simply expands the item. This behavior applies to fixed-sizing, as well (such as the flex-basis: 400px
in your code).
Again, the initial settings are:
min-width: auto
, in row-directionmin-height: auto
, in column-directionFor a more complete explanation see this post:
The standard solution to this problem is simple: override the default.
In your code, add min-width: 0
to .grow1
.
That solves the problem 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>
revised fiddle 1
In IE11, contrary to spec guidance, the flex min-width
/ min-height
default values are already 0
, yet the flex item still breaks out.
The defaults are 0
because when the flexbox spec was first released, the min-*
properties did not deviate from the CSS 2.1 initial values, which are 0
.
Later, after browsers had completed their implementations, the flex min-*
values were updated to auto
. Chrome, Safari, FF and Edge made the update. IE11 did not.
The reason the flex items break out in IE11 relates to another issue: the browser wants an explicit width on 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>
revised fiddle 2 (IE11)
Evidence appears to exist (in this question and other examples I've seen) that Webkit-based browsers are no longer honoring the auto
default defined in the spec.
Moreover, the adherence to the auto
standard may vary based on which property is used for sizing: flex-basis
vs. width
/ height
As discussed in the following post, these properties should render the same way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With