Skip to content

Commit 62d65ed

Browse files
committed
[css-grid-2] Draft up grid algo diff for per-axis subgrids; move issue text into an example to illustrate it.
1 parent b93e6f3 commit 62d65ed

File tree

1 file changed

+238
-92
lines changed

1 file changed

+238
-92
lines changed

css-grid-2/Overview.bs

Lines changed: 238 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -51,95 +51,6 @@ Introduction {#intro}
5151
██████ ███████ ████████ ██████ ██ ██ ████ ████████
5252
-->
5353

54-
<h2 id="subgrid-per-axis">
55-
Subgrids: per-axis proposal</h2>
56-
57-
<div class="issue">
58-
There is a proposal to have ''subgrid'' be instead a keyword
59-
for 'grid-template-rows' and 'grid-template-columns',
60-
which would allow subgridding to apply to a single axis,
61-
not only both axes simultaneously.
62-
The same constraints apply as specified for dual-axis subgrids via 'display',
63-
but only to the subgridded dimension.
64-
65-
As with the ''display: subgrid'' proposal,
66-
placement of all grid items, including subgrids and their sub-items,
67-
occurs before sizing,
68-
and track sizing in each axis is handled in independent steps
69-
as per the Grid Sizing Algorithm.
70-
In the case of a single-axis subgrid,
71-
the track sizing in a subgridded dimension treats each item in a given track in that axis
72-
as part of the parent grid;
73-
and in the other axis, the subgrid item is treated as a nested grid.
74-
75-
For example, suppose we have a parent grid container A
76-
which contains an item B that has subgridded columns
77-
and contains a grandchild C that has subgridded rows
78-
and grandchild C' that is simply a nested grid.
79-
When A sizes its columns it treats B's items slotted into to A's corresponding columns,
80-
but when A sizes its rows it treates B as a single item
81-
(a grid container with its own rows and some items including items C and C').
82-
Similarly when B sizes its rows,
83-
it treats C's items as slotted into B's rows,
84-
but when B sizes its columns,
85-
it treats C as a single item,
86-
just as it does with C'.
87-
There is no relationship between C's rows and A's rows,
88-
because the rows in B are nested, not subgridded.
89-
90-
At a high level, the grid algorithm is:
91-
92-
<ol>
93-
<li>Size the columns
94-
<li>Size the rows
95-
<li>Adjust the columns (if needed based on final row sizes)
96-
</ol>
97-
98-
The grid sizing algorithm in this example would thus look like this:
99-
<ol>
100-
<li>Resolve sizes of A’s grid columns,
101-
using the sizes of A’s grid items,
102-
treating B as empty but treating its children (including C and C') as items in grid A.
103-
104-
The grid algorithm simply recurses into C'.
105-
For C, it's more complicated:
106-
107-
<ol>
108-
<li>Size C's columns
109-
<li>Size C's rows by sizing B's rows
110-
<li>Adjust C's columns
111-
<li>Return C's final column sizes.
112-
</ol>
113-
114-
A correct size for B's rows requires C's final column sizes,
115-
because the row size depends on the column size,
116-
and thus B's rows could very well depend on C's final column sizes.
117-
To break this cyclic dependency, we need to split the algorithm to depend on the initial approximation of C's final column sizes, and do the adjustment pass later.
118-
So for C, we need to recurse into column sizing only, and pass that initial size up to A for its initial column sizing.
119-
120-
When we size B's rows later on, we will size C's rows (which are subgridded),
121-
and finish up C's sizing by finalizing its columns.
122-
If this resulted in a change, we have the opportunity
123-
to trigger an adjustment pass for A's columns during its adjustment pass.
124-
125-
<li>Next, resolve sizes of A's rows,
126-
using the sizes of A’s grid items,
127-
treating B as a single item.
128-
129-
Since B, as a subgrid, has its sizing is split out into the multiple passes,
130-
the grid algorithm issues only a row-sizing recursion into B:
131-
Size B’s rows, treating C’ as a single item, requesting its final size,
132-
and treating C as an empty item and hoisting its children as items in grid B.
133-
134-
B returns its final row size, which factors into A’s row sizing pass.
135-
136-
<li>Last, finalize A’s column sizes.
137-
If C’s final size changes as a result of the row-sizing pass through B,
138-
this should trigger a resizing of B’s columns,
139-
which should trigger a resizing pass on A’s column.
140-
</ol>
141-
</div>
142-
14354
<h2 id="subgrids">
14455
Subgrids</h2>
14556

@@ -226,7 +137,7 @@ Establishing a Subgrid: Per-Axis Proposal</h3>
226137
New values: subgrid
227138
</pre>
228139

229-
<dl dfn-for="display" dfn-type=value>
140+
<dl dfn-for="grid-template-rows, grid-template-columns" dfn-type=value>
230141
<dt><dfn>subgrid</dfn>
231142
<dd>
232143
Tracks are <a>subgridded</a> in this axis:
@@ -237,8 +148,8 @@ Establishing a Subgrid: Per-Axis Proposal</h3>
237148

238149
Issue: This syntax allows for subgrids which are subgridded in one <em>or</em> both axes.
239150

240-
<h2 id="subgrid-rules">
241-
Subgrid Rules</h2>
151+
<h3 id="subgrid-items">
152+
Characteristics of a Subgrid Item</h3>
242153

243154
Note: <ins>Insertions</ins> are differences between the dual-axis and per-axis proposals.
244155

@@ -334,6 +245,241 @@ Subgrid Rules</h2>
334245
Overflow must otherwise be treated as ''visible''.
335246
</ul>
336247

248+
<h3 id="subgrid-sizing">
249+
Subgrid Sizing Algorithm</h3>
250+
251+
Note: Placement of all grid items,
252+
including subgrids and their sub-items,
253+
occurs before sizing.
254+
255+
Issue: In this section, which is itself a diff,
256+
<i>italics</i> indicate additional prose
257+
specific to <a href="#subgrid-per-axis">per-axis subgrids</a>.
258+
259+
Track sizing in a subgridded dimension
260+
treats each item in a given track in that axis
261+
as members of the parent grid.
262+
This interlacing requires that grid sizing
263+
drills down per axis into subgrids,
264+
rather than completing both axes in its recursion.
265+
Thus the <a href="https://www.w3.org/TR/css-grid-1/#algo-overview">Grid Sizing Algorithm</a>
266+
is modified as follows:
267+
268+
<blockquote>
269+
270+
<ol>
271+
<li>
272+
First, the <a>track sizing algorithm</a> is used to resolve the sizes of the <a>grid columns</a>.
273+
274+
<ins>
275+
276+
<p>In this process,
277+
any <a>grid item</a> which is subgridded
278+
in the <a>grid container</a>’s <a>inline axis</a>
279+
is treated as empty
280+
and its <a>grid items</a> (the grandchildren)
281+
are treated as direct children of the <a>grid container</a> (their grandparent).
282+
This introspection is recursive.
283+
284+
<p><i>Items which are subgridded only in the <a>block axis</a>,
285+
and whose <a>grid container</a> size in the <a>inline axis</a>
286+
depends on the size of its contents
287+
are also introspected:
288+
since the size of the item in this dimension
289+
can be dependent on the sizing of its subgridded tracks in the other,
290+
the size contribution of any such item to this grid’s column sizing
291+
(see <a href="https://www.w3.org/TR/css-grid-1/#algo-content">Resolve Intrinsic Track Sizes</a>)
292+
is taken under the provision
293+
of having determined its track sizing only up to the same point
294+
in the Grid Sizing Algorithm as this parent grid itself.
295+
E.g. for the first pass through this step,
296+
the item will have its tracks sized only through this first step;
297+
if a second pass of this step is triggered then
298+
the item will have completed a first pass through steps 1-3
299+
as well as the second pass of this step
300+
prior to returning its size for consideration in this grid’s column sizing.
301+
Again, this introspection is recursive.</i></p>
302+
303+
</ins>
304+
305+
If calculating the layout of a <a>grid item</a> in this step
306+
depends on the <a>available space</a> in the <a>block axis</a>,
307+
assume the <a>available space</a> that it would have
308+
if any row with a <a>definite</a> <a>max track sizing function</a>
309+
had that size and all other rows were infinite.
310+
311+
<li>
312+
Next, the <a>track sizing algorithm</a> resolves the sizes of the <a>grid rows</a>,
313+
using the <a>grid column</a> sizes calculated in the previous step.
314+
315+
<ins>
316+
317+
<p>In this process,
318+
any <a>grid item</a> which is subgridded
319+
in the <a>grid container</a>’s <a>block axis</a>
320+
is treated as empty
321+
and its <a>grid items</a> (the grandchildren)
322+
are treated as direct children of the <a>grid container</a> (their grandparent).
323+
This introspection is recursive.
324+
325+
<p><i>As with sizing columns,
326+
items which are subgridded only in the <a>inline axis</a>,
327+
and whose <a>grid container</a> size in the <a>block axis</a>
328+
depends on the size of its contents
329+
are also introspected.
330+
(As with sizing columns,
331+
the size contribution to this grid’s row sizing
332+
is taken under the provision
333+
of having determined its track sizing
334+
only up to this corresponding point in the algorithm;
335+
and again, this introspection is recursive.)</i></p>
336+
</ins>
337+
338+
<li>
339+
Then, if the <a>min-content contribution</a> of any grid items have changed
340+
based on the row sizes calculated in step 2,
341+
steps 1 and 2 are repeated with the new <a>min-content contribution</a>
342+
and <a>max-content contribution</a> (once only).
343+
344+
<div class="note">
345+
This cycle is necessary for cases where the <a>inline size</a> of a <a>grid item</a>
346+
depends on the <a>block size</a> of its <a>grid area</a>.
347+
Examples include wrapped column <a>flex containers</a> (''flex-flow: column wrap''),
348+
<a>orthogonal flows</a> ('writing-mode'),
349+
and <a spec=css-multicol>multi-column elements</a>.
350+
</div>
351+
352+
<li>
353+
Finally, the <a>grid container</a> is sized
354+
using the resulting size of the <a>grid</a> as its content size,
355+
and the tracks are aligned within the <a>grid container</a>
356+
according to the 'align-content' and 'justify-content' properties.
357+
358+
Note: This can introduce extra space between tracks,
359+
potentially enlarging the grid area of any grid items spanning the gaps
360+
beyond the space allotted to during track sizing.
361+
</ol>
362+
363+
Once the size of each <a>grid area</a> is thus established,
364+
the <a>grid items</a> are laid out into their respective containing blocks.
365+
The <a>grid area’s</a> width and height are considered <a>definite</a> for this purpose.
366+
367+
Note: Since formulas calculated using only definite sizes,
368+
such as the <a>stretch fit</a> formula,
369+
are also definite,
370+
the size of a grid item which is stretched
371+
is also considered definite.
372+
373+
</blockquote>
374+
375+
Issue: Note, this means that a subgrid establishing an orthogonal flow
376+
would have the order of its track sizing inverted compared to a nested grid.
377+
We could simplify this by saying that an orthogonal flow
378+
cannot establish a subgrid; it can only be a nested grid.
379+
380+
<i>The following example illustrates how per-axis subgrids are sized:</i>
381+
382+
<div class="example" style="font-style: italic">
383+
For example, suppose we have a parent grid container <var>A</var>
384+
which contains an item <var>B</var> that has subgridded columns
385+
and contains a grandchild <var>B</var> that has subgridded rows
386+
and grandchild <var>D</var> that is simply a nested grid.
387+
388+
<xmp>
389+
<grid-A>
390+
<grid-B subgrid=columns>
391+
<grid-C subgrid=rows/>
392+
<grid-D>
393+
</grid-B>
394+
<grid-A>
395+
</xmp>
396+
397+
When <var>A</var> sizes its columns
398+
it treats <var>B</var>'s items
399+
as slotted into to <var>A</var>'s corresponding columns,
400+
but when <var>A</var> sizes its rows
401+
it treates <var>B</var> as a single item
402+
(a grid container with its own rows and some items including items <var>C</var> and <var>D</var>).
403+
Similarly when <var>B</var> sizes its rows,
404+
it treats <var>C</var>'s items as slotted into <var>B</var>'s rows,
405+
but when <var>B</var> sizes its columns,
406+
it treats <var>C</var> as a single item,
407+
just as it does with <var>D</var>.
408+
There is no relationship between <var>C</var>'s rows and <var>A</var>'s rows,
409+
because the rows in <var>B</var> are nested, not subgridded.
410+
411+
At a high level, the grid algorithm is:
412+
413+
<ol>
414+
<li>Size the columns
415+
<li>Size the rows
416+
<li>Adjust the columns (if needed based on final row sizes)
417+
</ol>
418+
419+
The grid sizing algorithm in this example would thus look like this:
420+
<ol>
421+
<li>
422+
<strong>Resolve sizes of <var>A</var>’s grid columns,
423+
using the sizes of <var>A</var>’s grid items,
424+
treating <var>B</var> as empty
425+
but treating its children
426+
(including <var>C</var> and <var>D</var>)
427+
as items in grid <var>A</var>.</strong>
428+
429+
The grid algorithm simply recurses into <var>D</var>.
430+
For <var>C</var>, it's more complicated:
431+
432+
<ol>
433+
<li>Size <var>C</var>'s columns.
434+
<li>Size <var>C</var>'s rows by sizing <var>B</var>'s rows.
435+
<li>Adjust <var>C</var>'s columns.
436+
<li>Return <var>C</var>'s final column sizes.
437+
</ol>
438+
439+
A correct size for <var>B</var>'s rows
440+
requires <var>C</var>'s final column sizes,
441+
because the row size depends on the column size,
442+
and thus <var>B</var>'s rows could very well depend
443+
on <var>C</var>'s final column sizes.
444+
To break this cyclic dependency,
445+
we need to split the algorithm to depend on
446+
the initial approximation of <var>C</var>'s final column sizes,
447+
and do the adjustment pass later.
448+
So for <var>C</var>, we need to recurse into column sizing only,
449+
and pass that initial size up to <var>A</var>
450+
for its initial column sizing.
451+
452+
When we size <var>B</var>'s rows later on,
453+
we will size <var>C</var>'s rows (which are subgridded),
454+
and finish up <var>C</var>'s sizing by finalizing its columns.
455+
If this resulted in a change, we have the opportunity
456+
to trigger an adjustment pass for <var>A</var>'s columns
457+
during its adjustment pass.
458+
459+
<li>
460+
<strong>Next, resolve sizes of <var>A</var>'s rows,
461+
using the sizes of <var>A</var>’s grid items,
462+
treating <var>B</var> as a single item.</strong>
463+
464+
Since <var>B</var>, as a subgrid,
465+
has its sizing is split out into the multiple passes,
466+
the grid algorithm issues only a row-sizing recursion into <var>B</var>:
467+
Size <var>B</var>’s rows, treating D as a single item, requesting its final size,
468+
and treating <var>C</var> as an empty item
469+
and hoisting its children as items into grid <var>B</var>.
470+
471+
<var>B</var> returns its final row size,
472+
which factors into <var>A</var>’s row sizing pass.
473+
474+
<li>
475+
<strong>Last, finalize <var>A</var>’s column sizes.</strong>
476+
If <var>C</var>’s final size changes
477+
as a result of the row-sizing pass through <var>B</var>,
478+
this should trigger a resizing of <var>B</var>’s columns,
479+
which should trigger a resizing pass on <var>A</var>’s column.
480+
</ol>
481+
</div>
482+
337483
<h2 id=alignment>
338484
Aspect-ratio&ndash;controlled Gutters</h2>
339485

0 commit comments

Comments
 (0)