Re: [css-grid] Flexible Track Sizing & Indefinite Avail Size

On Wed, Sep 2, 2015 at 4:58 PM, Javier Fernandez <jfernandez@igalia.com> wrote:
> On 09/16/2014 10:11 PM, Tab Atkins Jr. wrote:
>> On Wed, Aug 27, 2014 at 8:17 AM, François REMY
>> <francois.remy.dev@outlook.com> wrote:
>>> Dear CSS Grid editors,
>>>
>>> I’m trying to understand the reasons behind the choice of the sizing
>>> algorithm of flexible tracks under no definite size constraint. As a
>>> reminder, please find quoted here the algorithm in question:
>>>
>>> # The used flex fraction is the maximum of:
>>> #
>>> # - Each flexible track’s base size divided by its flex factor.
>>> #
>>> # - The result of finding the size of an fr for each grid item
>>> #    that crosses a flexible track, using all the grid tracks
>>> #    that the item crosses and a space to fill of the item’s
>>> #    max-content contribution.
>>> #
>>> Also, if the plan is to make the layout system stable for flex factors
>>> approaching zero (like flexbox), then this first set of constraints will be
>>> annoying (as a very small flex factor can create huge track breadths (with a
>>> smart epsilon/epsilon-squared pair of flex factor; see test case), while a 0
>>> flex factor is identical to no flex at all which may result in collapsed
>>> columns).
>>
>> Nah, factors <1 get handled slightly differently to maintain proper
>> behavior.  It took me a bit to work it out, but it makes a lot of
>> sense:
>
> I understand that this idea fits perfectly when dealing with flexible
> tracks in
> a definite sized container, because we indeed want either to fill or
> fraction
> proportionally (based on the flex factors) the *available space*.
> However, in
> the  case of indefinite containers, there is no such "available space to
> fill or
> fraction".
>
> The spec precisely states to use the value 1 instead of the sum of factors
> when trying to "find the size of a fr", but not when considering the
> "track’s
> base size divided by its flex factor" value. We want the maximum of these
> values to be considered as "used flex fraction", so assuming a value of 1
> for all the tracks with  <1fr won't allow us to keep proportions between
> them (we will get always their baseSize as it will be bigger) and between
>>1fr tracks.
>
> I'll try to use an example now:
>
> .grid {
>     display: grid;
>     grid-template-columns: 50px;
>     grid-template-rows: minmax(min-content, 0.5fr) minmax(18px, 2fr);
>     font: 10px/1 Ahem;
>    width: 50px;
> }
>
> <div class="grid">
>      <div class="firstRowFirstColumn">XXXXX XXXXX XXXXX XXXXX</div>
>      <div class="secondRowFirstColumn" ></div>
> </div>
>
> Let's focus on grid item's height, which is computed using the flex track
> sizing algorithm when available space is indefinite:
>
> 1-First, find the used flex fraction:
>   * Maximum of baseSize / factor for each flex track
>     - track1: baseSize: 40px / factor: 0.5 = 200px
>         + factor 1 => 40px
>     - track2: baseSize: 18px / factor: 2 = 36px
>     - max = 200px or 40px (depending on whether we assume or not a
> factor value of 1)

Ignoring the obvious 200px typo (you meant 20px), you were supposed to
*divide*, not multiply - you wrote down the equation correctly, just
did the opposite operation.  So the answers are actually 80px/40px for
track 1, and 9px for track 2.

>  * Maximum result when finding the size of an fr for each grid item that
> crosses a flexible track, using all the grid tracks that the item
> crosses and a space to fill of the item’s max-content contribution.
>    - track1:
>        + leftover space:  spaceToFill (40px) - base sizes of the
> non-flexible tracks (0px) = 40px
>        + flex factor sum: 0.5 < 1 => 1
>        + hypothetical fr size: leftover space  / flex factor sum = 40px
>        + hypothetical fr size * flexible track’s flex factor = 20px <
> track’s base size (40px)
>            - restart this algorithm treating all such tracks as inflexible.
>   - track2
>        + leftover space:  spaceToFill (0px) - base sizes of the
> non-flexible tracks (0px) = 0px
>        + flex factor sum: 2
>        + hypothetical fr size: leftover space  / flex factor sum = 0px
>        + hypothetical fr size * flexible track’s flex factor = 0px <
> track’s base size (18px)
>            - restart this algorithm treating all such tracks as inflexible.
>
> 2- If we use 1 as factor value for tracks with <1fr, the used used flex
> fraction is 40px
>    - track1: used flex fraction (40px) * flex factor (0.5) = 20px <
> baseSize ( 40px ) => 40px
>    - track2:  used flex fraction (40px) * flex factor (2) = 80px
>
> * Issue1: I'm not sure how to deal with the "restart", since there are
> nor more flex tracks to process.

Then the flex factor sum is 0 (an empty sum is always 0), which gets
corrected to 1, and the hypothetical fr size is set to the leftover
space.

> * Issue2: When using 1 as value for <1fr, the results are not
> proportional, since track2 might be 4x.

Your math was off enough that I'm not sure what you're basing this off
of.  Let's run through it (assuming we correct <1 to 1):

* First track yields an fr size of 40px.
* Second track yields an fr size of 9px.
* First item yields an fr size of 40px.
* Second item yields an fr size of 0px.

So, the size of an fr is 40px.

* 40px*.5 is 20px, less than the first track's base size, so no change
- it remains 40px.
* 40px*2 is 80px, greater than the second track's base size, so its
base size is set to 80px.

This does change the ratio, from 4x to 2x.  But that's okay!  If you'd
used 5fr and 20fr, that would maintain a 4x ratio, but we're dealing
with something below 1.  We don't want a .01fr item to make the entire
thing blow up; in particular, a 0fr item doesn't influence the size of
the fr *at all*, and we should make sure that the behavior approaches
that in the limit.  That's what we get here; .5fr has a lesser effect
on the size of the fr than it would naively appear.

> * Issue3: If we don't use 1, we get the expected results, but then we
> need a way to deal with division
> by zero in the computation of " Maximum of baseSize / factor for each
> flex track".

Division by zero isn't the only problem. ^_^ If the first track was
.01fr, and we naively maintained ratios, it would make the second item
8000px tall.  That's an outcome we want to avoid.

>> Basically, you're asking each track "what size should we give an fr to
>> make you maximally happy?".  For elements with >=1fr, they want to
>> fill the available space, so their answer is just the available space
>> divided by their fr value, so that when things multiply back out,
>> they're exactly filling the space, as desired.  For elements with <1
>> fr, they want to fill a *fraction* of the space, not the whole thing;
>> thus, they want 1fr to equal the available space, so that when things
>> multiply back out, they're filling the desired fraction of the space,
>> as desired.
>
> Actually, there is another sentence in the spec that makes me wonder
> if this applies to indefinite sized containers:
>
> "When the available space is infinite (which happens when the grid
> container’s width or height is indefinite), flex-sized grid tracks are
> sized to their contents while retaining their respective proportions.
> The used size of each flex-sized grid track is computed by determining
> the max-content size of each flex-sized grid track and dividing that
> size by the respective flex factor to determine a “hypothetical 1fr
> size”. The maximum of those is used as the resolved 1fr length (the flex
> fraction), which is then multiplied by each grid track’s flex factor to
> determine its final size."
>
> The sentence **flex-sized grid tracks are sized to their contents while
> retaining their respective proportions** make me think that we don't
> want to fraction the content-sized space, just to make it bigger
> proportionally, based on the flex factors. Hence, "0.1fr 0.2fr" should
> produce the same results than "1fr 2fr".

Nah, we don't want that.

So: I'll edit the spec to make the "indefinite" clause also clamp to 1.

~TJ

Received on Friday, 4 September 2015 18:04:42 UTC