2

please look at my very simple example of flex layout:

There is

  • container with
    • flex box turned on (display: flex)
    • wrapping (flex-wrap: wrap)
  • some items in it that have
    • flex-grow is set to 1 = all items will scale equally
    • flex-shrink is 0 = any items will not be scale down
    • flex-basis = all items have same base width

Despite all the rulesets, items in last row have different width? How it this possible when the flex-grow says that all items will be scaled equally?

Quote from http://www.w3schools.com/cssref/css3_pr_flex-grow.asp:

The flex-grow property specifies how much the item will grow relative to the rest of the flexible items inside the same container.

That's cool, but my items in last row grow little bit more that others. Any ideas?

flex {
  display: flex;
  flex-wrap: wrap;
}
item {
  flex: 1 0 4rem;
  height: 4rem;
  margin: 0.5rem;
  border: 1px solid lightblue;
}
<flex>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
</flex>
hippietrail
  • 15,848
  • 18
  • 99
  • 158
pravdomil
  • 2,961
  • 1
  • 24
  • 38
  • How about changing `1 0 4rem` to `1 0 auto`? – Stickers Apr 01 '16 at 13:53
  • Well I need to have the items with same width. If I set that to auto it varies of content inside. – pravdomil Apr 01 '16 at 14:00
  • What about `0 0 4rem`? The question is a bit confusing. – Stickers Apr 01 '16 at 14:05
  • Closer, almost there, items are equal. But I want to fill the empty space on the right. http://i.imgur.com/MUJlU6i.png – pravdomil Apr 01 '16 at 14:15
  • This is not possible with flexbox...that's not the way the line box model works. – Paulie_D Apr 01 '16 at 14:17
  • I agree with Paulie_D, but if you're ok with a fixed number of items in each row and ok to use percentage width, it's probably doable. – Stickers Apr 01 '16 at 14:22
  • Oh...and [**Flex-grow:1 does not mean what you think it means**](https://css-tricks.com/flex-grow-is-weird/) – Paulie_D Apr 01 '16 at 14:31
  • well container will have variable width and variable number of items, only basis in px will be specified, but I found a solution for this, check http://codepen.io/pravdomil/pen/RaLpMm?editors=1100 this is perfect, but I want to get rid of the hack – pravdomil Apr 01 '16 at 14:37
  • @Paulie_D I understand now, it distributes the rest of space at the end of the row, thanks for resourse – pravdomil Apr 01 '16 at 14:42
  • I'm not sure if that is what you want when the browser window is rather wide, you will still be seeing the whitespace on the right. – Stickers Apr 01 '16 at 14:45
  • well I works for normal sizes of browser window, but you are right if your browser is too wide, there will be whitespace on blank, this is small workaround for now – pravdomil Apr 01 '16 at 14:58
  • the conclusion is: not possible in CSS – pravdomil Apr 01 '16 at 15:12
  • Instead of the hack, you can try a pseudo-element: http://stackoverflow.com/q/34928565/3597276 – Michael Benjamin Apr 01 '16 at 19:28

2 Answers2

3

The flex grow and shrink factors are basically used to Resolve Flexible Lengths. But that happens independently for each flex line (row or column).

To resolve the flexible lengths of the items within a flex line: [...]

  • If using the flex grow factor

    Find the ratio of the item’s flex grow factor to the sum of the flex grow factors of all unfrozen items on the line. Set the item’s target main size to its flex base size plus a fraction of the remaining free space proportional to the ratio.

  • If using the flex shrink factor

    For every unfrozen item on the line, multiply its flex shrink factor by its inner flex base size, and note this as its scaled flex shrink factor. Find the ratio of the item’s scaled flex shrink factor to the sum of the scaled flex shrink factors of all unfrozen items on the line. Set the item’s target main size to its flex base size minus a fraction of the absolute value of the remaining free space proportional to the ratio.

The CSS Working Group is aware of this problem and plans to introduce some way to fix it in Flexbox Level 2

Solve the “items on the last line get way too big when you're flexing” problem. More generally, “make items have a consistent flexed size, regardless of how much extra space is on each line”.

  • Possible solution - fill out the last line with “phantom copies” of the last item, flex with them in, then remove them.
  • Possible solution - calculate minimum values of 1fr and alignment free space across the entire flexbox (instead of per-line) and use that.
Oriol
  • 274,082
  • 63
  • 437
  • 513
3

it is easy by add css just like:

.flexlast::after{ //here use after add a element
    content: "  ";
    flex: 100;    //100 just big enough, maybe 50 is ok too.
}

flex {
  display: flex;
  flex-wrap: wrap;
}
item {
  flex: 1 0 4rem;
  height: 4rem;
  margin: 0.5rem;
  border: 1px solid lightblue;
}
flex::after{
    content: "  ";
    flex: 100;     
}
<flex>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
</flex>
defend orca
  • 617
  • 7
  • 17
  • 1
    I want to like this but it goes wrong when the last row has the exact right number of items, the `::after` item squeezes in and ruins alignment. – clockworkgeek Apr 26 '23 at 10:33