w3c / csswg-drafts

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

[css-contain-3][css-grid-2] Interaction between subgrid, and containment. #7091

Open bfgeek opened 2 years ago

bfgeek commented 2 years ago

Most layout algorithms only allow communicate with their direct children. When size container queries are present this is important as we can:

  1. Determine the size of the block.
  2. Determine the style for its children.
  3. Enter into the layout algorithm knowing that all the children will have their correct style (and importantly we don't need to know what the grandchildren's style is yet).

There are 2-3[*] exceptions to this rule.

  1. Tables. Table layout walks 3 levels deep (table -> section -> row -> cell), and before we know the size of the section, and row. Tables however are fine for container queries - as the container query can only apply to the top-level table element - and not the individual internal table parts. (As per - https://drafts.csswg.org/css-contain-1/#containment-size ).

  2. Subgrid. Similar to tables subgrid layout can walk N levels deep (depending on how many nested subgrids there are) before we know the size of the individual subgrid elements. I.e. we'll walk N levels deep during placement, and sizing of the grid.

An example where I believe the containment principle could be being violated in the FF implementation of subgrid at the moment:

<!DOCTYPE html>
<div style="display: grid; grid-template: auto / 100px 100px; border: solid;">
  <div style="display: grid; grid-template-rows: subgrid; contain: size;">
    <div style="background: lime; height: 100px;"></div>
  </div>
  <div style="background: hotpink;"></div> <!-- This sizes to 100px tall. This is picked up from the grandchild within the size contained element. -->
</div>

There are broadly two solutions here.

  1. Follow tables, inlines, etc. and disallow containment on subgrids.
  2. Make grids that have a subgridded axis behave as a "standalone grid", that is they wont participate in the parts grid layout.

[*] 3rd one is inlines but different to top level layout algorithms.

Loirooriol commented 2 years ago

I think I would expect something like this:

  1. Size the grid under a max-content constraint. Treat the subgrid as empty due to containment, so the grid becomes 0px tall.
  2. This sets the size of the grid container: 0px content height.
  3. Run the grid algorithm again, now with a definite available grid space, and not treating the subgrid as empty.
  4. This sets the final size of the grid: 100px tall.
bfgeek commented 2 years ago

Run the grid algorithm again, now with a definite available grid space, and not treating the subgrid as empty.

It shouldn't matter if the outer grid (which I think you're referring to here) has a definite size or not. If you re-run the grid algorithm you'll reset any sizes of the columns/rows, (and the subgrid doesn't have a defined size at this point). If you inspect children here you'd break containment afaict.

I believe we'll need either option (1) or (2) above as with container queries you can have grandchildren change their grid-template (e.g. a grandchild may go from grid-template-columns: subgrid to grid-template-columns: initial) or change their grid-area affecting placement, along with a whole host of other things.

Loirooriol commented 2 years ago

You are right, I was only considering the parent grid container. But if the items in the subgrid can affect the track sizes of the parent grid, then this will in turn affect the sizes of the subgrid container, breaking containment.

tabatkins commented 2 years ago

We had earlier resolved on (2) for layout containment, see the definition of the subgrid keyword:

If there is no parent grid, or if the grid container is otherwise forced to establish an independent formatting context (for example, due to layout containment [CSS-CONTAIN-2]), the used value is the initial value, none, and the grid container is not a subgrid.

For size containment, could you elaborate on what you think might be problematic? The definition of size containment will cause the subgrid to lay out (and affect its parent grid) as if it were empty, which seems well-defined and unproblematic; after the parent grid has sized, the subgrid will have definite sizes for its tracks, and can do layout of its items normally. Are there complications we're missing?

fantasai commented 1 year ago

This needs clarification in either css-contain or css-grid, that the grid items do not participate in sizing the parent grid's tracks.

Loirooriol commented 1 year ago

When size container queries are present

Note that if a subgrid becomes a query container for size queries, then it also gets layout containment, so it establishes an independent formatting context and stops being a subgrid.

From #7822, it may also be worth clarifying how contain: inline-size interacts with subgrids (or even with normal grids).

mirisuzanne commented 1 year ago

My understanding was that we want to contain layout information from getting out of the layout-contained element, but it sounds like you're saying we also don't allow layout information to flow into the contained element? Is there a reason for that?