Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do flex items wrap instead of shrink?

Tags:

html

css

flexbox

I wonder if anyone could give me a simple intro about how flexbox layout gets calculated, especially in which priority order, for example:

    <div id="container" style="display: flex; flex-direction: row; flex-wrap:wrap;">
    <div style="flex: 1 0 200px; height:200px; background-color: lightgreen;"></div>
    <div style="flex: 1 1 400px; height:200px; background-color: lightyellow;"></div>
    <div style="flex: 1 0 200px; height:200px; background-color: lightblue;"></div>
</div>

I find it interesting that if I make the container width smaller than 600px; the wrap will take effect first before the shrinking (I set the second yellow block to flex: 1 1 400px;) which turn into 3 rows, then the shrinking take effect until container reach 200px;

I wonder what is the order/rule the flexbox layout get decided? Why it does not just shrink from 400 block?

And even I also set all three blocks to flex: 1 1 their basis size; the wrap still happens first.

Thanks

like image 315
Kuan Avatar asked Sep 12 '16 19:09

Kuan


2 Answers

See Flex Layout Algorithm in the spec:

  1. Initial Setup
  2. Line Length Determination
  3. Main Size Determination
  4. Cross Size Determination
  5. Main-Axis Alignment
  6. Cross-Axis Alignment
  7. Resolving Flexible Lengths
  8. Definite and Indefinite Sizes
  9. Intrinsic Sizes

First, at step 3, flex items are collected into flex lines.

Later, at step 7, they flex (grow, shrink, or remain unaltered).

So yes, flex-wrap, which determines how flex items are collected into flex lines, has more "priority" than flex-shrink.

like image 138
Oriol Avatar answered Oct 06 '22 18:10

Oriol


The flex-shrink property often comes in handy in a single-line flex container (flex-wrap: nowrap).

In other words, when the flex items cannot wrap, flex-shrink will enable them to shrink when the container is too small (the spec calls this negative free space). This has the effect of preventing flex items from overflowing the container.

However, in a multi-line flex container (flex-wrap: wrap) no negative free space is created most of the time because flex items can create additional lines. An exception is when a multi-line container in, let's say, row-direction, is narrow enough to wrap all items. This leaves items stacked in a single column. Now they will shrink or hold firm, depending on flex-shrink (demo).

You have a row-direction, wrap-enabled flex container with three flex items.

  • div #1 ~ flex: 1 0 200px
  • div #2 ~ flex: 1 1 400px
  • div #3 ~ flex: 1 0 200px

When the container is greater than 800px, all items stay on the line.

When the container breaks below 800px, div #3 will wrap (there is no need to shrink, even if it could).

At the 600px mark (the combined width of divs #1 & #2), div #2 wraps. Again, no need to shrink.

#container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
div:nth-child(1) {
  flex: 1 0 200px;
  height: 200px;
  background-color: lightgreen;
}
div:nth-child(2) {
  flex: 1 1 400px;
  height: 200px;
  background-color: lightyellow;
}
div:nth-child(3) {
  flex: 1 0 200px;
  height: 200px;
  background-color: lightblue;
}
<div id="container">
  <div></div>
  <div></div>
  <div></div>
</div>

From the spec:

flex-shrink

[This property] specifies the flex shrink factor, which determines how much the flex item will shrink relative to the rest of the flex items in the flex container when negative free space is distributed.

like image 29
Michael Benjamin Avatar answered Oct 06 '22 18:10

Michael Benjamin