CSS Flex positioning gotchas: child expands to more than the width allowed by the parent
Please note that for the sake of simplicity, all of the following discussion is based on flex-direction: row
Problem Description
You have a flex
container which has 4 children and it displays them in a row.
child1 has width: 48px
width,
child3 has width: 48px
width,
child4 has width: 150px
width,
(we can also use flex-basis
instead of width)
you want child2 to occupy the rest of the space, so what do you do?
set flex-grow: 1
on child2.
This works fine if the content of child2 is less than the available width, and even if the content of child2 grows, it automatically wraps to next line.
Gotcha1:
Let’s add white-space: nowrap
into the mix, now something interesting happens, child2 grows as much as it wants to without being restricted, shrinks the other flex children (if they are allowed to) and extends outside the width of the parent. It seems like the parent does not control the width anymore.
Why? Would you expect it to behave this way? I certainly didn’t. I expected its width to be constrained as flex-grow: 1
should only allow it to take up the available space and not expand beyond that, and possibly show an overflow in case the text is not allowed to be wrapped.
( try setting an explicit overflow. Setting overflow: auto
works, overflow: hidden
works as well, and both work the same )
Explanation:
By default the min-width
of a flex child is set to auto
, so when the content grows beyond the available width and it can’t wrap, it is still not constrained until you set an explicit min-width
(or an explicit width
) on the flex child.
Gotcha 2:
Interestingly, this also works with explicitly setting the overflow
property on the child in question.
But when would you like this to happen? Wouldn’t you rather wrap your content for child2 to multiple lines? Why set white-space: nowrap
?
Let’s see a use case:
You would like to fix the width for child 1, 3 and 4 and constraint child2 so that it shows ellipsis if the content of child2 is too long.
Gotcha 3:
Do remember that you always have to explicitly constraint the immediate flex child, which means if you have a child of child2 and you are trying to show ellipsis on text-overflow
, you would still have to set overflow
or min-width
on child2
Gotcha 4:
Also, text-overflow
does not work on display: flex
elements, so if you want child2 content to be shown as ellipsis on overflow, you can’t set text-overflow: ellipsis
on child2, instead you should just wrap the text in a container inside child2 and set the text-overflow
, whitespace
and overflow
properties on this container, and constrain child2 using min-width/overflow/width
Gotcha 5:
you would think that width
and flex-basis
would work the same and constrain the flex child, seems like that isn’t the case.
Gotcha 6:
setting width: 0
and min-width: 0
has different effects,
also, both of them handle the layout fine, but the text is still overflown outside the flex parent. The behaviour seems to differ in how much overflown text is shown. min-width: 0
shrinks the other children and width: 0
does not, both of them do not let the element expand beyond the parent.
This is most likely based on the initial value considered for the calculation of flex-grow child and other children. width: 0
would start initial layout calculations from 0 and then finding out that there is empty space so growing the element, while min-width: 0
would probably start the calculation from the available space and based on that distribute the space. (I haven’t explored this yet)
Gotcha 7:
setting width: 0
or flex-basis: 0
does not actually mean the flex element would have 0 width. It is just used as an initial indication of the size and the actual size is decided based on values of other properties (for eg, the flex-grow
and flex-shrink
properties)
There are other combinations which can be explored, for example min-width: 0
does not seem to work with setting flex-shrink: 0
, but setting width: 0
works.
References:
- https://drafts.csswg.org/css-flexbox/#min-size-auto
- https://stackoverflow.com/questions/39884226/why-does-an-element-with-flex-1-width-0-still-have-width
- https://stackoverflow.com/questions/34352140/what-are-the-differences-between-flex-basis-and-width
- https://stackoverflow.com/questions/36968138/nested-flex-elements-dont-make-parent-grow
- https://stackoverflow.com/questions/7985021/css-flexbox-issue-why-is-the-width-of-my-flexchildren-affected-by-their-content/7985973#7985973
- https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size
- https://westerndevs.com/css/Using-Overflow-Ellipsis-in-Inline-Flex/