-
Notifications
You must be signed in to change notification settings - Fork 707
/
Copy pathOverview.bs
323 lines (268 loc) · 13.3 KB
/
Overview.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
<pre class='metadata'>
Title: CSS Grid Layout Module Level 2
Shortname: css-grid
Level: 2
Status: UD
Group: csswg
Work Status: exploring
ED: https://drafts.csswg.org/css-grid-2/
Editor: Tab Atkins Jr., Google, http://www.xanthir.com/contact/, w3cid 42199
Editor: Elika J. Etemad / fantasai, Invited Expert, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Rossen Atanassov, Microsoft, ratan@microsoft.com, w3cid 49885
Abstract: This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
</pre>
Introduction {#intro}
=====================
This level is currently maintained as a diff spec over the level 1 module [[!CSS-GRID-1]].
<h2 id="grid-model">
Grid Containers</h2>
<h3 id='grid-containers'>
Establishing Grid Containers: the ''subgrid'' 'display' value</h3>
<a>Subgrids</a> provide the ability to pass grid parameters down through nested elements,
and content-based sizing information back up to their parent grid.
<pre class="propdef">
Name: display
New values: subgrid
</pre>
<dl dfn-for="display" dfn-type=value>
<dt><dfn>subgrid</dfn>
<dd>
If the element is a <a>grid item</a>
(i.e. it is in-flow and its parent is a <a>grid container</a>),
this value makes the element a <a>subgrid</a>
(which is a special type of <a>grid container</a> box, see [[#subgrids]])
and consequently ignores its 'grid-template-*' and 'grid-*-gap' properties
in favor of adopting the parent grid tracks that it spans.
Otherwise,
it behaves as ''grid''.
</dl>
<div class="issue">
There is a proposal to have ''subgrid'' be instead a keyword
for 'grid-template-rows' and 'grid-template-columns',
which would allow subgridding to apply to a single axis,
not only both axes simultaneously.
The same constraints apply as specified in <a href="#subgrids"></a>,
but only to the subgridded dimension.
As with the ''display: subgrid'' proposal,
placement of all grid items, including subgrids and their sub-items,
occurs before sizing,
and track sizing in each axis is handled in independent steps
as per the Grid Sizing Algorithm.
In the case of a single-axis subgrid,
the track sizing in a subgridded dimension treats each item in a given track in that axis
as part of the parent grid;
and in the other axis, the subgrid item is treated as a nested grid.
For example, suppose we have a parent grid container A
which contains an item B that has subgridded columns
and contains a grandchild C that has subgridded rows
and grandchild C' that is simply a nested grid.
When A sizes its columns it treats B's items slotted into to A's corresponding columns,
but when A sizes its rows it treates B as a single item
(a grid container with its own rows and some items including items C and C').
Similarly when B sizes its rows,
it treats C's items as slotted into B's rows,
but when B sizes its columns,
it treats C as a single item,
just as it does with C'.
There is no relationship between C's rows and A's rows,
because the rows in B are nested, not subgridded.
At a high level, the grid algorithm is:
<ol>
<li>Size the columns
<li>Size the rows
<li>Adjust the columns (if needed based on final row sizes)
</ol>
The grid sizing algorithm in this example would thus look like this:
<ol>
<li>Resolve sizes of A’s grid columns,
using the sizes of A’s grid items,
treating B as empty but treating its children (including C and C') as items in grid A.
The grid algorithm simply recurses into C'.
For C, it's more complicated:
<ol>
<li>Size C's columns
<li>Size C's rows by sizing B's rows
<li>Adjust C's columns
<li>Return C's final column sizes.
</ol>
A correct size for B's rows requires C's final column sizes,
because the row size depends on the column size,
and thus B's rows could very well depend on C's final column sizes.
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.
So for C, we need to recurse into column sizing only, and pass that initial size up to A for its initial column sizing.
When we size B's rows later on, we will size C's rows (which are subgridded),
and finish up C's sizing by finalizing its columns.
If this resulted in a change, we have the opportunity
to trigger an adjustment pass for A's columns during its adjustment pass.
<li>Next, resolve sizes of A's rows,
using the sizes of A’s grid items,
treating B as a single item.
Since B, as a subgrid, has its sizing is split out into the multiple passes,
the grid algorithm issues only a row-sizing recursion into B:
Size B’s rows, treating C’ as a single item, requesting its final size,
and treating C as an empty item and hoisting its children as items in grid B.
B returns its final row size, which factors into A’s row sizing pass.
<li>Last, finalize A’s column sizes.
If C’s final size changes as a result of the row-sizing pass through B,
this should trigger a resizing of B’s columns,
which should trigger a resizing pass on A’s column.
</ol>
</div>
<!--
██████ ██ ██ ████████ ██████ ████████ ████ ████████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ████████ ██ ████ ████████ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ████████ ██████ ██ ██ ████ ████████
-->
<h2 id="subgrids">
Subgrids</h2>
A <a>grid item</a> can itself be a <a>grid container</a> by giving it ''display: grid'';
in this case the layout of its contents will be independent of the layout of the grid it participates in.
In some cases it might be necessary for the contents of multiple <a>grid items</a> to align to each other.
A <a>grid container</a> that is itself a <a>grid item</a>
can defer the definition of its rows and columns to its parent <a>grid container</a>
by using ''display: subgrid'',
making it a <dfn export>subgrid</dfn>.
In this case, the <a>grid items</a> of the <a>subgrid</a>
participate in sizing the <a>grid</a> of the parent <a>grid container</a>,
allowing the contents of both grids to align.
<div class="example">
For example, suppose we have a form consisting of a list of inputs with labels:
<pre class="lang-html">
<ul>
<li><label>Name:</label> <input name=fn>
<li><label>Address:</label> <input name=address>
<li><label>Phone:</label> <input name=phone>
</ul>
</pre>
We want the labels and inputs to align, and we want to style each list item with a border.
This can be accomplished with subgrid layout:
<pre>
ul {
display: grid;
grid: auto-flow / auto 1fr;
}
li {
display: subgrid;
grid-column: span 2;
margin: 0.5em;
border: solid;
padding: 0.5em;
}
label {
grid-column: 1;
}
input {
grid-column: 2;
}
</pre>
</div>
A <a>subgrid</a> behaves just like a normal <a>grid container</a> except that:
<ul style="list-style-type: lower-alpha">
<li>
The number of explicit tracks is given by its <a>grid span</a>,
rather than by 'grid-template-rows'/'grid-template-columns'.
<li>
The <a>grid-placement properties</a> of the <a>subgrid</a>’s <a>grid items</a>
are scoped to the lines covered by the subgrid.
E.g., numeric indices count starting from the first line of the subgrid
rather than the first line of the parent grid.
<li>
The <a>subgrid</a> itself lays out as an ordinary <a>grid item</a> in its parent grid,
but acts as if it was completely empty for sizing purposes.
The <a>subgrid</a>'s own <a>grid items</a> participate in the sizing of its parent grid and are aligned to it.
In this process, the sum of the <a>subgrid</a>'s margin, padding, and borders at each edge
are applied as an extra layer of margin to the items at those edges.
<div class="example">
For example, if we have a 3×3 grid with the following tracks:
<pre>#parent-grid { grid-template-columns: 300px auto 300px; }</pre>
If a subgrid covers the last two tracks,
its first two columns correspond to the parent grid's last two columns,
and any items positioned into those tracks participate in sizing the parent grid.
Specifically, an item positioned in the first track of the subgrid
influences the auto-sizing of the parent grid's middle track.
<pre>
#subgrid { grid-column: 2 / span 2; } /* cover parent's 2nd and 3rd tracks */
#subgrid > :first-child { grid-column: 1; } /* subgrid's 1st track, parent grid's 2nd track */
</pre>
If the subgrid has margins/borders/padding,
the size of those margins/borders/padding also influences sizing.
For example, if the subgrid has 100px padding:
<pre>#subgrid { padding: 100px; }</pre>
Then a <a>grid item</a> in the <a>subgrid's</a> first track
acts as if it has an additional ''100px'' of top, left, and bottom margin
influencing the sizing of the parent grid's tracks
and the <a>grid item's</a> own position.
</div>
<li>
The 'grid-gap' properties do not apply to subgrids.
(Their items are instead spaced by the 'grid-gap' of their parent grid,
since they are laid out in the parent grid.)
<li>
The <a>subgrid</a> does not have any <a>implicit grid tracks</a>;
every <a>grid area</a> within it is <a>clamped</a> to its <a>explicit grid</a>.
<div class="example">
For example, if a ''span 1'' subgrid has a <a>grid item</a> with ''grid-column: 2 / span 3;'',
then that item is instead forced into (and limited to) the first (only) track in the subgrid.
</div>
<li>
The <a>subgrid</a> is always stretched in both dimensions:
the 'align-self'/'justify-self' properties on it are ignored,
as are any specified width/height constraints.
<li>
Layoutwise, the <a>subgrid</a>’s <a>explicit grid</a>
is always aligned with the corresponding section of the parent <a>grid</a>;
the 'align-content'/'justify-content' properties on it are also ignored.
<li>
The UA <em>may</em> apply 'overflow' to <a>subgrids</a>
so the contents of the subgrid can be scrolled aside.
(Note: the act of scrolling does not affect layout.)
Overflow must otherwise be treated as ''visible''.
<li>
Since <a>subgrids</a> can be placed before their contents are placed,
their lines automatically receive the line names specified on the parent <a>grid</a>.
</ul>
<!--
██ ██ ███ ██████ ███████ ██ ██ ████████ ██ ██
███ ███ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██
████ ████ ██ ██ ██ ██ ██ ████ ██ ██ ██ ████
██ ███ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ████████ ██
██ ██ █████████ ██ ██ ██ ██ ████ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██
██ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██
-->
<h2 id=masonry>
Masonry Layout</h2>
<div class=issue>
People have been trying to use CSS for <a href="https://github.com/w3c/csswg-drafts/issues/1009#issuecomment-278095001">masonry layouts</a> for over a decade,
and it doesn't seem to have slowed,
so it's probably not just a layout fad.
Would probably be worthwhile to address officially.
As far as I can tell,
this is best done as a Grid feature;
some of the features I've seen in masonry libraries
(like large items spanning multiple masonry tracks)
make Flexbox inappropriate.
This also would reuse *so many* Grid features
that it would be a shame to put together a brand new layout spec for it.
No clue what it would look like yet, tho.
In handwavey terms, it's a grid that's only gridded
"in one dimension",
and free-flows in the other,
with auto-flow.
Note that this is actually 100% possibly with Grid today,
if your items are of known height,
by making thousands of 1px tall rows,
and setting the items' row-span to be equal to their height in px.
(Or some lower-res multiple, like 10px rows.)
Dense row auto-flow then magically makes Masonry happen.
This is just a terrible hack that runs into memory/CPU issues
due to the large number of rows.
It suggests, tho,
that making it work properly
is mostly a matter of relaxing some constraints,
rather than adding entirely new behavior.
</div>