Skip to content

Commit

Permalink
[css-grid-1][masonry] Make intrinsic sizing not depend on placement #…
Browse files Browse the repository at this point in the history
  • Loading branch information
fantasai committed Oct 19, 2023
1 parent fae0709 commit 633c049
Showing 1 changed file with 40 additions and 79 deletions.
119 changes: 40 additions & 79 deletions css-grid-3/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -168,51 +168,36 @@ Line Name Resolution</h3>
The [[css-grid-2#line-placement|line name resolution]]
works exactly is in <a href="https://www.w3.org/TR/css-grid/">CSS Grid</a>.

<h3 id="grid-item-placement">
Grid Item Placement</h3>

[=Grid items=] are placed using these steps:

<ol>
<li>
Place the items as if the [=masonry axis=]
had ''grid-template-columns/none'' specified in that axis.
<h3 id="track-sizing">
Grid Axis Track Sizing</h3>

<li>
For any items that were placed at the first (hypothetical) implicit line
in the [=masonry axis=] in step 1,
those items keep their placement in both axes as their final placement.
They will be laid out first in each [=grid axis=] track
and their [=grid axis=] placement is considered definite henceforth.
All other items ignore their placement from step 1.
Any item with a specified definite placement in the [=masonry axis=]
that doesn't result in it being placed at the first implicit line
in the [=masonry axis=]
will be treated as having ''grid-area/auto''-placement in that axis.
Track sizing works the same as in [[css-grid-2#algo-track-sizing|CSS Grid]],
except that when considering which items contribute to intrinsic sizes:
* All items explicitly placed in that track contribute, and
* All items without an explicit placement contribute

<li>
Place items using the [[#masonry-layout-algorithm|Masonry layout algorithm]] below.
</ol>
<div class="example">
For example, suppose there are two columns in the [=grid axis=]
and that
* Items A, B, and C have no explicit placement.
* Item D is explicitly placed into the first column.

(The reason for step 1 above is to determine which items contribute
to intrinsic track sizing in the [=grid axis=];
see [[#track-sizing]] below.)
In this case, items A, B, C, and D all contribute to sizing the first column,
<em>and</em> A, B, and C (but not D) contribute to the second column.
</div>

<h3 id="track-sizing">
Grid Axis Track Sizing</h3>
In the case of spanning items with no explicit placement,
their size contribution is divided by their spanning size.

Track sizing works the same as in [[css-grid-2#algo-track-sizing|CSS Grid]],
except that that the algorithm is run only with
the subset of items that have a known [=grid axis=] placement.
This subset contains the items placed at the first implicit line in the [=masonry axis=]
in <a href="#grid-item-placement">Grid Item Placement</a> above,
plus the items that have a specified definite placement in the [=grid axis=],
plus the items that span all [=grid axis=] tracks
(which obviously will be placed at the first implicit line
since there is no other way to place them).
Other items will be placed in the [=grid axis=] by the [[#masonry-layout-algorithm]] below
and don't contribute to intrinsic track sizing
(because that would create circular dependencies).
Note: This algorithm ensures that each track is at least big enough
to accommodate every item that is ultimately placed in it,
and does not create dependency cycles between placement and track sizing.
However, depending on the variation in sizes,
tracks could be larger than necessary:
an exact fit is only guaranteed if
all items are explicitly placed in the [=grid axis=]
or all items are the same size
(or matching multiples of that size, in the case of spanning items).

<h4 id="repeat-auto-fit">
repeat(auto-fit)</h3>
Expand All @@ -234,60 +219,39 @@ Masonry Layout Algorithm</h3>
Items are placed in [=order-modified document order=],
but items with a definite placement are placed
before items with an indefinite position (as in regular grid layout).

For each of the tracks in the [=grid axis=],
keep a <dfn>running position</dfn> initialized to zero.
For each item placed at the first implicit line in the [=masonry axis=]
in <a href="#grid-item-placement">Grid Item Placement</a> step 1 above:

First for each item with a definite placement in the [=grid axis=],
then for each item with an indefinite placement:
<ol>
<li>
Position the item at the [=content edge=] of the [=grid container=] in the [=masonry axis=]
and at its start track in the [=grid axis=].

<li>
Calculate the size of the <a href="#containing-block">containing block</a>
and then layout the item.
Then, calculate its resulting [=margin box=] in the [=masonry axis=].
Set the [=running position=] of the [=grid axis=] tracks the item spans
to the maximum of <code>margin-box-end + grid-gap</code>
and the current [=running position=] of those tracks.
</ol>

Note: This means that items with a definite placement at line 1 in the [=masonry axis=]
by <a href="#grid-item-placement">Grid Item Placement</a> step 1
can be made to intentionally overlap.

The remaining items get their final placement using the following steps:
<ol>
<li>
If the item has an indefinite placement in the [=grid axis=],
then resolve its definite placement in the [=grid axis=] using these substeps:
If the item has an definite placement in the [=grid axis=],
use that placement.
Otherwise, resolve its [=grid axis=] placement using these substeps:

<ol>
<li>Starting at the first [=grid axis=] line in the implicit grid...
<li>Starting at the first [=grid axis=] line in the [=implicit grid=].
<li>Find the largest [=running position=] of the [=grid axis=] tracks
that the item would span if it were placed at this line,
and call this position <code>max_pos</code>.
and call this position <var>max_pos</var>.
<li>Increment the line number and repeat step 2
until the item would no longer fit inside the grid.
<li>Pick the line that resulted in the smallest <code>max_pos</code>
<li>Pick the line that resulted in the smallest <var>max_pos</var>
as the item's definite placement in the [=grid axis=].
</ol>

Otherwise, a definite placement in the [=grid axis=] is honored
the same as in a regular grid.

<li>
Position the item at its [=grid axis=] start track
and the maximum of the [=running position=]s
of the tracks it spans.
Place the item in its [=grid axis=] tracks
at the maximum of the [=running position=]s
of the tracks it spans.

<li>
Calculate the size of the item's <a href="#containing-block">containing block</a>
and then layout the item.
Then calculate its resulting [=margin box=] in the [=masonry axis=].
Set the [=running position=] of the [=grid axis=] tracks the item spans
to <code>max_pos + margin-box-end + grid-gap</code>.
Set the [=running position=] of the spanned [=grid axis=] tracks
to <code><var>max_pos</var> + <var>margin-box-end</var> + <var>grid-gap</var></code>.
</ol>

<h3 id="masonry-auto-flow">
Expand Down Expand Up @@ -363,10 +327,7 @@ The Implicit Grid</h2>
The [=implicit grid=] is formed in the same way as for a regular [=grid container=].
However, it's only used in the [=grid axis=].
The flow axis specified by ''grid-auto-flow'' is ignored:
items are always placed by filling the [=grid axis=]
(though note that the ''grid-auto-flow'' property's ''grid-auto-flow/dense'' keyword
does have an effect in determining which items end up at line 1 in the [=masonry axis=],
in [[#grid-item-placement]] step 1).
items are always placed by filling the [=grid axis=].
''direction:rtl'' reverses the grid if the [=inline axis=] is the [=grid axis=]
(as usual for a regular [=grid container=])
and it makes items flow from right to left if the [=inline axis=] is the [=masonry axis=].
Expand Down

0 comments on commit 633c049

Please sign in to comment.