1

In flexbox, if you set flex-flow: column nowrap and the elements inside have non-zero value of flex shrink, they should shrink down to all fit inside the flex container.

I have found that if you have only one item in this container and it has content bigger than the flex-container then it will not shrink down. But if other elements are included in the container (if it is not the only item) then it will shrink down.

Best visualized in this CodePen.

Here is the same code from the CodePen.

.container {
  padding: 10px;
  height: 100px;
  width: 100px;
  background: red;
  margin: 5px 20px;
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
}

.item {
  width: 80px;
  height: 40px;
  background: blue;
  margin: 5px;
  /* same as
  flex: 1 1 40px;
  */
}

.super.item {
  height: 200px;
}

.item div {
  width: 10px;
  height: 150px;
  background: black;
}

body {
  margin: 0;
  display: flex;
}
<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'>
  </div>
</div>

<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'>
    <div></div>
  </div>
</div>

<div class='container'>
  <div class='item super'>
  </div>
</div>

<div class='container'>
  <div class='item super'>
    <div></div>
  </div>
</div>

Is there an explanation on why that last div does not shrink to fit the flex container?

Dejan.S
  • 18,571
  • 22
  • 69
  • 112
Lou Bagel
  • 1,001
  • 8
  • 11
  • 1
    Well stating the obvious here but the content inside is pushing it to expand. If you have a div inside a div that does not have flex will behave like that, it is called overflow. You can solve this in different ways depending on your needs and wanted results. Can you provide more information for me to give the best answer or was this enough? – Dejan.S May 31 '19 at 06:07
  • Why does it expand in the 4th .container but not the 2nd? – Lou Bagel May 31 '19 at 06:23
  • 1
    Because in the 4th `.container` you're expanding its height by using the class `super`. – tcj May 31 '19 at 06:28
  • Ah the super class. So if a flex item has a set size or larger content it will shrink but not if both... – Lou Bagel May 31 '19 at 06:30
  • I found a work around but it uses `height: fit-content`, I won't show it as `fit-content` is only partially suported by browsers. Maybe @Dejan.S has a better solution. – tcj May 31 '19 at 07:39
  • Are you happy with the information me and tcj provided? Or are you looking for a eventually looking for a solution to a specific issue you have? – Dejan.S May 31 '19 at 10:30
  • the answer is simple, you are setting heights that are different across all your examples and confusing your self. To start with, you cannot compare any of those because we don't have the same constraint .. for the last one you set a big height (bigger than the content) and for the first ones you set a small height (smaller than the content) then check the duplicate to understand the min-height contraint that apply to your element which is in the last case the height of the content and the first case the height you set – Temani Afif May 31 '19 at 11:07
  • The answer in the duplicate question link answers it: setting `overflow:hidden` or `min-height:0` results in what I expected—as in the item shrinking regardless of content length. I use `overflow:hidden` often so probably just used to that. I did confuse myself a bit in my CodePen but the point was to slightly change the CSS on each iteration—that was intentional. I'm good now, thanks for the comments. – Lou Bagel May 31 '19 at 18:25

3 Answers3

1

What about making the height of those contents inherit their parent's one?

.super.item {
  height: inherit;
}
.item div {
  width: 10px;
  height: inherit;
  background: black;
}

Snippet below, is that what you're trying to achieve? :

.container {
  padding: 10px;
  height: 100px;
  width: 100px;
  background: red;
  margin: 5px 20px;
  display: flex;
  flex-flow: column nowrap;
  align-items: center; 
}

.item {
  width: 80px;
  height: 40px;
  background: blue;
  margin: 5px;
  /* same as
  flex: 1 1 40px;
  */
}

.super.item {
  height: inherit;
}

.item div {
  width: 10px;
  height: inherit;
  background: black;
}

body {
  margin: 0;
  display: flex;
}
<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'>
  </div>
</div>

<div class='container'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'>
    <div></div>
  </div>
</div>

<div class='container'>
  <div class='item super'>
  </div>
</div>

<div class='container'>
  <div class='item super'>
    <div></div>
  </div>
</div>
tcj
  • 1,645
  • 4
  • 13
  • 21
0

I don't know if you are talking about it or not. Your div is taking width and height as item. so whenever you add another div it will add height of 150px.

.item div{
  width: 10px;
  height: 150px;
  background: black;
}
susie
  • 163
  • 2
  • 17
  • Yes, but as you can see in the 2nd box the (blue) element shrinks to the flex container. The CSS is identical with the only difference being sibling elements. – Lou Bagel May 31 '19 at 06:16
  • @LouBagel the CSS is not identical, that's your issue. One element is having 40px height and another 200px height and this is a *big* difference – Temani Afif May 31 '19 at 11:14
0

Very simple rule for items of a flexbox:
Items grow value is 0 and shrink is 1 and the base-case is auto.
flex: 0 1 auto

So

.item{
  width: 80px;
  height: 40px;         # will be used as base-case
  background: blue;
  margin: 5px;
  /* same as
  flex: 1 1 40px;
  */
}

Why does second container's item shrink? Easy. base-case is 40px or on the other hand it dose not have the class .super. Add .super and see what happens.

<div class='container'>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'>            # flex's item height: 40px;
        <div></div>               # regular div
    </div>
</div>

Why the third container that has the class .super does shrink? while height: 200px and it should overflow? Easy. it is the same as: flex: 0 1 200px (this is not quite right, see the comment below, what @TemaniAfif has pointed out)

try it:

.super.item{
/*   height: 200px; */
  flex: 0 1 200px;            # equal to height: 200px
}

now try this:

.super.item{
/*   height: 200px; */
  flex: 0 0 200px;            # turn off auto grow / shrink
}

Why the fourth overflows?. Easy. the item has a child that is a regular div

<div class='container'>
  <div class='item super'>         # flex's item
    <div></div>                    # regular div
  </div>
</div>

and the height of this div is 150px

.item div{
  width: 10px;
  height: 150px;               # remove this one, it shrinks
  background: black;
}
Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
  • `flex: 1 1 200px` is different from `height:200px` – Temani Afif May 31 '19 at 11:10
  • `Items shrink or expand value is 1` --> only the shrink is 1, the expand (grow) is 0 by default – Temani Afif May 31 '19 at 11:13
  • @TemaniAfif Thank you to mention my mistakes. yes I am wrong about the second one the initial value is: `flex: 0 1 auto`, but about the first one can you please tell me where is the difference? – Shakiba Moshiri May 31 '19 at 11:41
  • here is an example: https://jsfiddle.net/rba7qwfy/ and this difference is the key for this question – Temani Afif May 31 '19 at 11:49
  • @TemaniAfif. So the different is about `min-height`? right? The one with `flex` is longer then the first one since `min-height: auto` but not for the first one? And for the first one `min-height: 0` is the default. If yes I am confused why `auto` adds more size the the box. – Shakiba Moshiri May 31 '19 at 12:07
  • min-height is auto for both of them ... and the auto value is computed to 100px for the one where we have set 100px height and it computes to 120px (the inner content) where we have set flex that's why the second on is taller ... min-height:auto consider the content height AND the element height (flex-basis come after) – Temani Afif May 31 '19 at 12:09
  • @TemaniAfif Confusing :(. Where does **inner content** come form? I removed `border` & `margin` and there is no content but the second one is still taller!!! – Shakiba Moshiri May 31 '19 at 12:21
  • the div inside that has 120px height is the *inner content* – Temani Afif May 31 '19 at 12:21
  • @TemaniAfif Thanks for answering me. Still I cannot figure it out and need to read more. Anyway if my answer is wrong tell me so I will delete it. – Shakiba Moshiri May 31 '19 at 12:30