Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate flex shrink when flex items have a different flex basis

Tags:

flexbox

Let's say I have a simple flex container with 2 flex items where the flex items' sizes exceed the containers size - where flex-shrink will be used..like so:

.container {
  width: 600px;
  outline: 5px solid;
  display: flex;
}
section {
  flex: 0 1 600px;
  background: salmon;
}
aside {
  flex: 0 1 200px;
  background: aqua;
}
<div class="container">
  <section>
    <h2>Main content here</h2>
  </section>
  <aside>
    <h2>Some side content</h2>
  </aside>
</div>

Codepen demo

In the above example: The container is 600px, the section flex-item has flex basis of 600px and the aside has flex-basis of 200px - so the negative space is 200px.

So being that both flex items have the same flex-shrink factor of 1 - I expected that both flex items would shrink by 100px with the section getting a width of 600px - 100px = 500px and the aside getting 200px - 100px = 100px

But the result was actually that the section shrinks by 150px to 450px and the aside shrinks by 50px to 150px

So then I looked at the spec and I found this:

Note: The flex shrink factor is multiplied by the flex base size when distributing negative space. This distributes negative space in proportion to how much the item is able to shrink, so that e.g. a small item won’t shrink to zero before a larger item has been noticeably reduced.

So now I understand that when calculating flex-shrink on a flex item not only is the flex shrink factor taken into account, but also the flex base size (here, defined by the flex-basis property)

The problem is that I can't seem to do the math to calculate flex-shrink.

So just to continue with the above example: say I change the shrink factor of the section to 2...

.container {
  width: 600px;
  outline: 5px solid;
  display: flex;
}
section {
  flex: 0 2 600px;
  background: salmon;
}
aside {
  flex: 0 1 200px;
  background: aqua;
}
<div class="container">
  <section>
    <h2>Main content here</h2>
  </section>
  <aside>
    <h2>Some side content</h2>
  </aside>
</div>

Codepen demo #2

... the result is that section gets a width of 428px and aside gets a width of 121px

Can someone explain how to calculate this?

like image 537
Danield Avatar asked Apr 11 '16 13:04

Danield


People also ask

How do you calculate flex-shrink?

To find the shrink factor for each, multiply its flex-shrink value by its flex-basis value (1×100px or 1×400px), then divide this by the combined sum of the flex-shrink multiply the flex-basis for all items (1×100px) + (1×400px) + (1×400px).

How do I reduce space between two flex items?

To set space between the flexbox you can use the flexbox property justify-content you can also visit all the property in that link. We can use the justify-content property of a flex container to set space between the flexbox.

What is Flex-grow flex-shrink flex-basis?

Conclusion. As a final recap: flex-basis controls how large an element will be along the main-axis before any growing or shrinking occurs. Flex-grow determines how much it will grow in proportion to sibling elements, and flex-shrink determines how much it will shrink.

Does Flex-basis override width?

When declared, flex-basis will override the width / height property set on a flex container. If no flex-basis is specified the default is the set width / height value, if width / height isn't specified the default is the width / height of the content.

What is the use of flex shrink?

Definition and Usage. The flex-shrink property specifies how the item will shrink relative to the rest of the flexible items inside the same container. Note: If the element is not a flexible item, the flex-shrink property has no effect.

What is the difference between flex-shrink and flex-basis?

The flex-shrink property specifies how much a flex item will shrink relative to the rest of the flex items. The value must be a number, default value is 1. The flex-basis property specifies the initial length of a flex item.

How is the Flex shrink factor calculated?

Note: The flex shrink factor is multiplied by the flex base size when distributing negative space. This distributes negative space in proportion to how much the item is able to shrink, so that e.g. a small item won’t shrink to zero before a larger item has been noticeably reduced.

What is the Flex-shrink property in JavaScript?

Take your JavaScript to the next level at Frontend Masters . The flex-shrink property is a sub-property of the Flexible Box Layout module. It 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 there isn’t enough space on the row.


1 Answers

Neglecting lots of details, the algorithm is something like this

let sumScaledShrinkFactors = 0,
    remainingFreeSpace = flexContainer.innerMainSize;
for (let item of flexItems) {
  remainingFreeSpace -= item.outerFlexBasis;
  item.scaledShrinkFactor = item.innerFlexBasis * item.flexShrinkFactor;
  sumScaledShrinkFactors += item.scaledShrinkFactor;
}
for (let item of flexItems) {
  let ratio = item.scaledShrinkFactor / sumScaledShrinkFactors;
  item.innerWidth = item.innerFlexBasis + ratio * remainingFreeSpace;
}

So the formula is like

flexBasis * (1 + shrinkFactor / sumScaledShrinkFactors * remainingFreeSpace)

First case

1*600px + 1*200px ─┐               width 
                   │              ───────
600px * (1 + 1 / 800px * -200px) = 450px 
200px * (1 + 1 / 800px * -200px) = 150px 
                            │     ───────
600px - (600px + 200px) ────┘      600px 

Second case

2*600px + 1*200px ──┐               width 
                    │              ───────
600px * (1 + 2 / 1400px * -200px) ≈ 429px 
200px * (1 + 1 / 1400px * -200px) ≈ 171px 
                             │     ───────
600px - (600px + 200px) ─────┘      600px 
like image 86
Oriol Avatar answered Sep 25 '22 01:09

Oriol