- From: Daniel Holbert <dholbert@mozilla.com>
- Date: Fri, 18 Apr 2014 12:08:51 -0700
- To: www-style <www-style@w3.org>, "Tab Atkins Jr." <jackalmage@gmail.com>
On 04/18/2014 10:44 AM, Daniel Holbert wrote: > THE PROBLEM: > ============ > Basically, the problem arises from these facts: > (a) The flex-shrink value of a given element can impact the "original > desired free space" calculation for other elements, *even when the sum > of the flex-shrink values is less than 1*, due to the way flex-shrink > factors are scaled/renormalized. (Note that this isn't true of flex-grow > values that sum to less than 1, which makes this not a problem for > flex-grow.) [...] > So, the problem is that we calculate each item's "originally desired > free space", and then we discover that one item needs to be frozen, and > then for the remaining items, we *still* use their "original desired > free space" values as the [negative] free space that they take, even > though these values were calculated under the assumption that the frozen > element would be taking some of the [negative] free space. I'll expand on this a bit, with some concrete numbers & exact steps from the algorithm. I'll be comparing the 1st & 2nd examples from my testcase here: http://people.mozilla.org/~dholbert/tests/flexbox/flex-shrink-1.html So in both examples, we have a flex container with main-size 250px, and two flex items, whose flex base sizes are 200px and 100px. The first flex item also has "min-width:200px" (keeping it from actually shrinking), and has a flex-shrink of either 0.6 (first example) or 0.1 (second example). The second flex item has a flex-shrink of 0.4. Steps below are from section 9.7: http://dev.w3.org/csswg/css-flexbox/#resolve-flexible-lengths Step 1: The used flex factor is "flex-shrink". Step 2: (nothing happens) Step 3: Free space = 250px-(200px+100px) = -50px Step 4, for the FIRST EXAMPLE: a) sum the flex-shrink factors: 0.6 + 0.4 = 1.0 b) Multiply each flex-shrink factor by its flex base size: first item: 0.6 * 200px = 120 second item: 0.4 : 100px = 40 (which sum to 160) c) Renormalize flex shrink factors to sum to 1.0 (from (a)): first item: 120 * 1.0/160 = 0.75 second item: 40 * 1.0/160 = 0.25 d) Multiply those ^ by free space to get orig desired free space: first item: 0.75 * -50px = -37.5px second item: 0.25 * -50px = -12.5px Step 4, for the SECOND EXAMPLE: a) sum the flex-shrink factors: 0.1 + 0.4 = 0.5 b) Multiply each flex-shrink factor by its flex base size: first item: 0.1 * 200 = 20 second item: 0.4 : 100 = 40 (which sum to 60) c) Renormalize flex shrink factors to sum to 0.5 (from (a)): first item: 20 * 0.5/60 = 0.1667 second item: 40 * 0.5/60 = 0.3333 d) Multiply those ^ by free space to get orig desired free space: first item: 0.1667 * -50px = -8.33px second item: 0.3333 * -50px = -16.67px (So as you can see, we end up arriving at **different** "originally desired free space" values for the second item (-12.5px vs -16.67px), when we vary the **first item's** flex-shrink value.) Then we end up entering the loop (Step 5): - On the first loop iteration, we freeze the first flex item. - On the second loop iteration, we set the second flex item's "desired free space" to its originally desired free space value calculated above (-12.5px in the first example, -16.67px in the second example), and then we add this "desired free space" to the second item's main size. So, we end up with the second item having a final width of 87.5px in the first example, and 83.33px in the second example. (Note that we skip the "normalize" step in the loop, since the free space is less than (more negative than) the sum of our desired free space values.) ~Daniel
Received on Friday, 18 April 2014 19:09:20 UTC