w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.36k stars 641 forks source link

[css-grid-2] Resolving indefinite grid spans in nested subgrids #6905

Open mattwoodrow opened 2 years ago

mattwoodrow commented 2 years ago

My understanding of the concept of indefinite/definite grid spans for subgrids is so that the explicit grid for a sub grid can be calculated without a dependency on item placement in the parent grid.

Consider this pseudo-code example:

<grid=auto / repeat(10, 10px)>
    <grid subgrid column= 1 / 4>
        <item row = 1 / 2 column= auto / auto></item>
        <grid subgrid=‘[][][][]’ row= 1 / 2 column=auto / auto>
        </grid>
    </grid>
</grid>

The innermost grid is a sub grid, with an indefinite column grid span, so we should use the <line-name-list> and compute a span of 3.

When doing placement of the innermost grid item into the middle grid, I believe we should interpret the column property as 'auto / span 3' (we may need to update 8.3.1 - Grid Placement Conflict Handling to prioritise the span from the sub grid <line-name-list> over both the -start and -end properties).

I think that'd mean we'd place the item at line 2, spanning 3 to line 5. That's outside of the explicit grid for the middle sub grid, so we'd clamp the end line back to 4.

We now have a sub grid that thinks it has 3 explicit tracks, but only spans across 2 tracks in its parent. Any computations done using the 3 value would be wrong, and need to be fixed.

I think it'd be possible to have the same situation without nested subgrids, but instead triggering the 'limiting large grids' clamping during placement of the subgrid item.

The only way I can think of to resolve this (without introducing the dependency on having completed placement in the parent grid) is to clamp the innermost grids span to the maximum number of tracks in the parent (either the global track maximum if a normal grid, or the number of explicit tracks if parent is a subgrid). We'd then need to change the placement algorithm to ensure that these items are placed far enough startward to prevent further clamp. In my example above, that'd mean the innermost grid item is placed at 1 / 4, and overlapping <item>.

Alternatively, we could have the dependency on placement in the parent grid, and then the concept of indefinite grid spans shouldn't be needed.

bfgeek commented 2 years ago

@dlibby-

ethanjv commented 2 years ago

There are two main things I digest from the spec regarding this issue:

  1. Even if a subgrid has an indefinite grid span because of either *-start or *-end definition is auto, the number of grid lines that the subgrid spans will be definite because of the grid-template-* definition (clamped to span at least 2 grid lines). I believe it's a bit confusing to phrase it like "indefinite" since there is an actual definition that governs the span size.

  2. From https://drafts.csswg.org/css-grid-2/#subgrid-tracks:

    Placing the subgrid creates a correspondence between its subgridded tracks and those that it spans in its parent grid.

To me, this implies that in order to know the actual grid lines of a subgrid we need to place it in its parent first. This assumption seems consistent when you think about placing items within a subgrid using line names that are inherited from the parent grid:

<grid=auto / [a] [b] [a] [b]>
    <item column=1 / 2></item>
    <subgrid column=2 / 4>
        <item column=a></item>
    </subgrid>
</grid>

In the example above, in order to place the innermost item, we need to know the placement of the subgrid so that we know which spanned grid lines are named "a". Thus, I think we already depend on the parent's placement.

fantasai commented 2 years ago

I agree with @ethanjv that placement within a subgrid depends on the subgrid being placed in the parent grid.

As for indefinite spans, I think these were intended as a convenience to the author. Handling them the same as a subgrid which has an explicit span that overflows its parent's grid limitations makes sense. Afaict we did fail to specify that case, so I think the fix here is to do that? This means that a subgrid might have fewer tracks than it expected, either because its parent is a subgrid and therefore has a fixed number of tracks, or because its parent is hitting the UA limit on grid tracks.

mattwoodrow commented 2 years ago

I'm not sure I see how indefinite spans make things easier.

Once we've placed the subgrid into the parent grid, we have an definite number of tracks that we span, and the subgrid must have exactly that number of tracks. We can't use the number of names from the grid-template-X: subgrid <> definition and have a different number of tracks without changing our placement in the parent.

fantasai commented 2 years ago

Your pseudo-code was slightly unclear, so just to make sure we're talking about the same thing, is the following what you meant by your example?

<div id=grandparent >
    <grid id=parent >
        <item style="grid-row: 1 / 2; grid-column: auto / auto"></item>
        <grid id=child></grid>
    </grid>
</grid>
<style>
    #grandparent {
        display: grid;
        grid: auto / repeat(10, 10px);
    }
    #parent {
        display: grid;
        grid: subgrid / subgrid;
        grid-column: 1 / 4;
        /* unspecified grid-row, thus "auto / span 1" by default */
    }
    #child {
        display: grid;
        grid: subgrid / subgrid [][][][];
        grid-row: 1 / 2;
        /* unspecified grid-column, thus "auto / span 3" from the subgrid lines */
    }
</style>

Once we've placed the subgrid into the parent grid, we have an definite number of tracks that we span, and the subgrid must have exactly that number of tracks.

Right.

We can't use the number of names from the grid-template-X: subgrid <> definition and have a different number of tracks without changing our placement in the parent.

Which is why we only calculate the span from the name list in cases where there is an indefinite span.

I'm not sure I see how indefinite spans make things easier.

It's so the author doesn't have to specify the span number in multiple places. It's very easy for the UA to correctly infer a number of tracks from a subgrid's line name list, and also easy for the author to miscount and have an inconsistent span vs track list, especially when making edits, so we're making the UA do the work here.

Afaict we did fail to specify that case, so I think the fix here is to do that?

This does seem to be correctly specified in https://www.w3.org/TR/css-grid-2/#subgrid-implicit

This means that a subgrid might have fewer tracks than it expected, either because its parent is a subgrid and therefore has a fixed number of tracks, or because its parent is hitting the UA limit on grid tracks.

We might want to add these implications as a note, though.

The alternative would be to allow the subgrid to have implicit tracks that overflow the subgrid, into tracks whose sizes and positions are borrowed from the parent grid but are physically outside the borders of the subgrid's box. (This could feel a little weird when mixed with overflow: scroll but it would work.)

~fantasai (and Tab)

fantasai commented 2 years ago

Added clarifications in ad4bda1f2

Let us know if anything remains unclear, or, if you'd like to raise the possibility of overflowing subgrid tracks with the WG. (I believe it was discussed earlier, but I can't find the minutes, and in any case I think Blink engineers weren't as involved as Gecko at the time so imho it's reasonable to bring up if you think it should be reconsidered.)

mattwoodrow commented 2 years ago

That example is indeed what I had in mind. The important part to me was the clarification that resolving the number of explicit tracks in a subgrid can't happen until placement of the subgrid item in the parent has been done.

Thanks for adding those clarifications, I think makes it much clearer!

mattwoodrow commented 2 years ago

Should we special case template-grid-XXX: subgrid without any specified line names? The current spec says that we should always use the number of explicit tracks (note the property specifies lines, not tracks), clamped at 1.

The line-names-002.html test case has grid: 50px / subgrid; grid-column: span 10 (on .subgrid). It seems likely the author intent there is to have a used grid span of 10 there, not 1.

Alternatively, we could change the definition of indefinite spans such that grid-column: span 10 was not included (since it's a pretty definite request for 10 columns).

The deciding case is probably what do when we have grid-column: span 10; grid-template-columns: subgrid [] [] [] []. That appears to be an explicit request for 10 columns, but also 3 columns, and we have to pick which to honour.

tabatkins commented 2 years ago

The deciding case is probably what do when we have grid-column: span 10; grid-template-columns: subgrid [] [] [] []. That appears to be an explicit request for 10 columns, but also 3 columns, and we have to pick which to honour.

Yup, and we have a well-specified tie-breaker for that in point b of the subgrid section - the span wins, with the template only coming into play if the span is indefinite.

mattwoodrow commented 2 years ago

The definition of indefinite span only requires the start or end property are auto, which I think makes ‘grid-column: span 10’ indefinite.

On Thu, 3 Feb 2022 at 1:05 PM, Tab Atkins Jr. @.***> wrote:

The deciding case is probably what do when we have grid-column: span 10; grid-template-columns: subgrid [] [] [] []. That appears to be an explicit request for 10 columns, but also 3 columns, and we have to pick which to honour.

Yup, and we have a well-specified tie-breaker for that in point b of the subgrid section - the span wins, with the template only coming into play if the span is indefinite.

— Reply to this email directly, view it on GitHub https://github.com/w3c/csswg-drafts/issues/6905#issuecomment-1028474089, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALAZSRCHUXGEDTDURE42B3UZHBFDANCNFSM5KRJJ6HA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you authored the thread.Message ID: @.***>

tabatkins commented 2 years ago

Ugh, you're right (https://drafts.csswg.org/css-grid-2/#grid-placement), but I'm pretty certain that's just a bad definition. I'll track down the history tomorrow.

tabatkins commented 2 years ago

Yeah, that definition is just thoroughly broken. It originates from when we un-delta'd Grid 2, as part of "editorial integration", but that wording never appears in Grid 1.

The definitions in Grid 1 seem to be less than ideal as well. This just plain needs fixing.

As far as I can tell, the notion we wanted to capture is just "is the span specified at all, either explicitly via a span keyword or implicitly via two lines". All we're concerned with is what to do when we have to default the span because it's completely unspecified; for normal grids we default it to 1, for subgrids we default it to the number of tracks implied by the line list if specified; otherwise 1.

@fantasai could you confirm my understanding here? You did the undelta-ing that produced the current language.

tabatkins commented 2 years ago

Okay, definitions fixed - a span is now either explicit (a 'span' is specified), implicit (two lines are specified), or automatic (neither of the preceding, defaulting to grid-template-* properties for subgrids).