Roland Seuhs
Roland Seuhs

Reputation: 1995

How to create a flex item that shrinks before it wraps?

As can be seen in this JS-Fiddle, I basically try to use this CSS to create two divs that should fullfill these requirements:

I don't understand this behavior, because I have set flex-shrink for the flex items, so they should be able to shrink - but they don't: If the narrower item would be less than 50% wide, it wraps.

.m {
  display: flex;
  flex-wrap: wrap;
}

.l_1 {
  background-color: red;
  flex: 1 1 50%;
}

.r_1 {
  background-color: yellow;
  flex: 1 1 50%;
}
<div class=m>

  <div class=l_1>
    left_______________________________________________X
  </div>

  <div class=r_1>
    right
  </div>


</div>

(Tested on Firefox and Chrome)

Upvotes: 7

Views: 6212

Answers (3)

thomasrutter
thomasrutter

Reputation: 117343

When wrapping is enabled, it takes the place of shrinking, so where there is a condition that would trigger shrinking, it wraps instead - until there is only one item in the row, and if that's still bigger than the container, then it will shrink.

So, you need to set flex-basis for all boxes to the minimum size that block should be before wrapping. Note: a box will never shrink further than its minimum content width, meaning you can set flex-basis to 0 and it will go by the minimum content width of each box.

Then, if you want the boxes to expand to fill the available space, then use the flex-grow property (first value in flex) to control the relative amount by which each one should grow.

Upvotes: 1

Michael Benjamin
Michael Benjamin

Reputation: 371223

The problem is not flex-shrink. The problem is flex-basis. You have it set to 50%.

This means that flex-grow will add free space to the flex-basis, and each item will wrap quickly, before it has an opportunity to shrink.

Switch from flex-basis: 50% to flex-basis: 0.

More specifically, instead of flex: 1 1 50% use flex: 1, which breaks down to this:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

Now flex-grow distributes free space equally – not proportionally – to both items, and they can shrink before they wrap.

(Here's a more in-depth explanation: Make flex-grow expand items based on their original size)

.m {
  display: flex;
  flex-wrap: wrap;
}

.l_1 {
  background-color: red;
  flex: 1;
}

.r_1 {
  background-color: yellow;
  flex: 1;
}
<div class=m>
  <div class=l_1>left_______________________________________________X</div>
  <div class=r_1>right</div>
</div>

revised fiddle

Upvotes: 6

keithjgrant
keithjgrant

Reputation: 12739

Flex-shrink will not apply with flex-wrap: wrap also applied. It will line wrap instead.

The only exception to this is when you only have one flex item in the row. Then it should allow for flex-shrink to apply.

Perhaps the appropriate fix is to only apply the flex-wrap within a media query, so it only happens in smaller viewports?

Upvotes: 0

Related Questions