-
Notifications
You must be signed in to change notification settings - Fork 708
/
Copy pathOverview.bs
1359 lines (1126 loc) · 47.6 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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class='metadata'>
Title: CSS Grid Layout Module Level 3
Shortname: css-grid
Level: 3
Status: FPWD
Prepare for TR: yes
Date: 2024-09-19
Work Status: Exploring
Group: csswg
TR: https://www.w3.org/TR/css-grid-3/
ED: https://drafts.csswg.org/css-grid-3/
Editor: Tab Atkins Jr., Google, http://www.xanthir.com/contact/, w3cid 42199
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Former Editor: Mats Palmgren, Mozilla, mailto:mats@mozilla.com
Editor: Jen Simmons, Apple, http://jensimmons.com/, w3cid 52801
Editor: Brandon Stewart, Apple, https://brandonstewart.net, w3cid 138640
Abstract: This module introduces masonry layout as an additional layout mode for <a href="https://www.w3.org/TR/css-grid-2/">CSS Grid</a> containers.
WPT Path Prefix: css/css-grid/masonry/tentative/
WPT Display: open
Markup Shorthands: css yes
Status Text: <strong>This specification represents two variations on the proposal for masonry layout. Feedback on the alternatives is welcome.</strong>
</pre>
<pre class=link-defaults>
spec: css-align-3;
type: value; for: align-content;
text: center;
text: stretch;
type: dfn; text: alignment baseline;
spec: css-grid-2; type: dfn;
text: auto-placement algorithm
text: computed track list
text: collapsed track
spec: css-flexbox-1;
type:property;
text: order
type:dfn;
text: order-modified document order
</pre>
<style>
:is(section, p).option {
border-right: 1em double;
padding-right: 1em;
}
:is(section, p).option.grid {
border-right-color: #be2596;
}
:is(section, p).option.masonry {
border-right-color: #96be25;
}
:is(span, a).option {
font-weight: bold;
}
:is(span, a).option * {
color: inherit;
}
:is(span, a).option.grid {
color: #be2596;
}
:is(span, a).option.masonry {
color: #658118
}
</style>
<h2 id='intro'>
Introduction</h2>
<em>This section is not normative.</em>
Grid Layout is a layout model for CSS
that has powerful abilities to control the sizing and positioning
of boxes and their contents.
Grid Layout is optimized for 2-dimensional layouts:
those in which alignment of content is desired in both dimensions.
<figure>
<img src="images/grid-layout.png"
alt="An example of grid layout:
two rows of items,
the first being four items — the last of which spans both rows,
and the second being two items —
the first of which spans the first two columns —
plus the spanned item from the first row.">
<figcaption>Representative Grid layout example</figcaption>
</figure>
Although many layouts can be expressed with regular Grid Layout,
restricting items into a grid in both axes also makes it impossible
to express some common layouts on the Web.
This module defines a layout system that removes that restriction
so that items can be placed into Grid-like tracks in just one of the axes,
while stacking them one after another in the other axis.
Items are placed into the column (or row) with the most remaining space
based on the layout size of the items placed so far.
This module also extends <a href="https://www.w3.org/TR/css-grid-2/">CSS Grid</a>
with this new grid item placement strategy
and <a href="https://drafts.csswg.org/css-align">CSS Box Alignment</a> with new alignment features.
<h3 id='background'>
Background and Motivation</h3>
[=Masonry layout=], sometimes also called “waterfall layout”,
is a common Web design pattern where a number of items--
commonly images or short article summaries--
are placed one by one into columns
in a way that loosely resembles stone masonry.
Unlike [[CSS-MULTICOL-1|multi-column layout]],
where content is placed vertically in the first column
until it must spills over to the second column,
[=masonry layout=] selects a column for each new item
such that it is generally closer to the top of the layout than items placed later.
<div class="example">
The Pinterest search results page exemplifies this layout:
<figure>
<img src="images/pinterest.png"
alt="An example of masonry layout:
four columns of items,
each item is placed into the column with the smallest height so far.">
<figcaption>Representative masonry layout example</figcaption>
</figure>
Here, each item has a different height
(depending on the content and the width of the column),
and inspecting the DOM reveals
(as the visual content itself gives no indication of ordering)
that each item has been placed into the column with the smallest height so far.
</div>
This layout superficially looks similar to multi-column layout;
but it has the advantage that scrolling down
will naturally lead to "later" items in the layout
(that is, those less relevant in the search results).
It's not possible to achieve this layout using earlier CSS layout models,
unless you know up-front how tall each item will be,
or use JavaScript for content measurement or placement.
<h3 id="alternative-proposals">
Alternative Syntax Proposals</h3>
<div class="issue">
The masonry layout feature of this specification is drafted with two different syntaxes
to promote debate and discussion of these two alternatives.
<dl>
<dt><dfn noexport><span class="option grid">Grid-integrated Option</span></dfn>
<dd>
In this syntax model, [=masonry layout=] is integrated into the [=grid layout=] model,
re-using all of the 'grid-*' properties.
<dt><dfn noexport><span class="option masonry">Grid-independent Option</span></dfn>
<dd>
In this syntax model, [=masonry layout=] is its own 'display' type,
and has its own parallel set of 'masonry-*' properties.
</dl>
</div>
<h3 id="values">
Value Definitions</h3>
This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from [[!CSS2]]
using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from [[!CSS-VALUES-3]].
Value types not defined in this specification are defined in CSS Values & Units [[!CSS-VALUES-3]].
Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions,
all properties defined in this specification
also accept the <a>CSS-wide keywords</a> as their property value.
For readability they have not been repeated explicitly.
<h2 id='masonry-model'>
Masonry Layout Model</h2>
<dfn>Masonry layout</dfn>
lays out items into pre-defined tracks similar to [=grid layout=] in one axis
(called the <dfn local-lt="grid-axis">grid axis</dfn>),
but flows them freely similar to [=flex layout=] in the other
(called the <dfn local-lt="stacking-axis">stacking axis</dfn>).
Similar to [=grid layout=] and unlike [=flex layout=],
[=masonry layout=]’s auto-placement
distributes items across the tracks to keep the lengths of those tracks
as similar as possible.
[=Grid items=] are formed and [=blockified=]
exactly the same as in a regular [=grid container=].
(For clarity, [=grid items=] and [=grid tracks=] of a [=masonry container=]
can be referred to as <dfn export lt="masonry item">masonry items</dfn>
and <dfn export lt="masonry track">masonry tracks</dfn>.)
All CSS properties work the same as in a regular [=grid container=]
unless otherwise specified by this specification.
For example, 'order' can be used to specify a different layout order for the items.
Note: Subgrid items are supported,
but subgridding only occurs in the [=grid axis=];
see [[#subgrids]] for details.
A <dfn>masonry container</dfn> is a box whose contents participate in [=masonry layout=].
A [=masonry container=] is a <dfn export>column masonry container</dfn>
if its [=stacking axis=] is the [=block axis=],
or a <dfn export>row masonry container</dfn>
if its [=stacking axis=] is the [=inline axis=].
<table class=data>
<caption>Establishing Masonry Containers</caption>
<thead>
<th>
<th><a href="#masonry-model-grid-option" class="option grid">Grid-integrated Syntax</a>
<th><a href="#masonry-model-masonry-option" class="option masonry">Grid-independent Syntax</a>
<th>Description
<tbody>
<tr>
<th style="writing-mode: vertical-rl; writing-mode: sideways-lr">
Column Masonry
<td>
<pre>
display: grid;
grid-template-columns: 1fr 2fr 3fr;
grid-template-rows: masonry;
</pre>
<td>
<pre>
display: masonry;
masonry-tracks: 1fr 2fr 3fr;
masonry-direction: column;
</pre>
<td>
<img src="images/masonry-columns.png"
alt="Column masonry lays out items in columns,
but ordered across the columns,
placing each item in the then-shortest column.">
<tr>
<th style="writing-mode: vertical-rl; writing-mode: sideways-lr">
Row Masonry
<td>
<pre>
display: grid;
grid-template-rows: 1fr 2fr 3fr;
grid-template-columns: masonry;
</pre>
<td>
<pre>
display: masonry;
masonry-tracks: 1fr 2fr 3fr;
masonry-direction: row;
</pre>
<td>
<img src="images/masonry-rows.png"
alt="Row masonry lays out items in rows,
but ordered down across the rows,
placing each item in the then-shortest row.">
</table>
<h3 id="order-accessibility">
Reordering and Accessibility</h3>
Although [=masonry layout=] generally progresses in a forwards fashion
(placing the next item down or endward of the current item,
matching the natural "reading order"),
it can switch between these two in a seemingly arbitrary manner.
In simple cases, the 'masonry-slack' property can help reduce
the feeling of backtracking due to small sizing differences in the [=block axis=]
when laying out auto-placed items.
But when [[#masonry-layout-algorithm|auto-placement]] is mixed with [=definite position|explicit placement=] or spanning items,
some amount of backtracking may occur.
<div class=example>
For example, in the following markup sample,
the fourth item is a spanner that doesn't fit
in the remaining empty column on the first line.
It ends up positioned into the into the first column,
which is the highest available space into which it will fit.
The next few items, which have a span of 1,
end up laying out “above” it in the empty column,
violating the natural reading order.
<xmp highlight=html>
<section class=masonry>
<div class=item>1</div>
<div class=item>2</div>
<div class="item tall">3</div>
<div class="item wide">4</div>
<div class=item>5</div>
<div class=item>6/div>
<div class=item>7</div>
</section>
<style>
.masonry {
display: masonry;
masonry-tracks: repeat(5, auto);
}
.item { height: 50px; }
.item.wide { masonry-track: span 3; }
.item.tall { height: 90px; }
</style>
</xmp>
<figure>
<img src="images/masonry-reorder-span.png"
alt="In this example, the first row is items 1, 2, 3, 5, 6,
with item 3 slightly taller than the others.
Item 4 spans the first three columns, and is placed
just below item 3, while item 7 is tucked under item 5.">
<figcaption>Auto-placed masonry layout with mixed-height items and mixed span sizes</figure>
</figure>
Similarly, items explicitly placed into specific tracks can leave gaps behind them,
into which subsequent auto-placed items can be placed visually out-of-order.
</div>
Authors should be aware of these possibilities
and design layouts where such backtracking is minimized
so that focus and reading order can be more easily followed.
Alternatively, if the items do not have an inherent order,
use the 'reading-flow' property to allow the UA to re-order the items
for reading and linear navigation.
ISSUE: Or should reordering be the default behavior for auto-placed items here?
<div class=note>
Techniques for reducing backtracking include:
* Using appropriate values for 'masonry-slack',
i.e. values large enough to avoid gratuitous differentiation among similarly-sized tracks,
but not so large that meaningful differences get ignored.
* Using explicit placement in ways that help group related items together,
rather than ways that disrupt the natural order of items
* Avoiding the combination of mixed span sizes in the [=grid axis=]
and disparate item sizes in the [=stacking axis=],
which can cause items to get pulled out of order (see example above).
</div>
As with [=grid layout=] and [=flex layout=]
authors can use the 'order' property to re-order items;
the same caveats apply.
See [[css-grid-2#order-accessibility]]
and [[css-flexbox-1#order-accessibility]].
<section class="option grid">
<h3 id="masonry-model-grid-option">
<span class="option grid">Grid-integrated Option:</span> Establishing Masonry Layout</h3>
<h4 id="grid-template-masonry">
Indicating the stacking axis: the ''grid-template-columns/masonry'' keyword for 'grid-template-columns'/'grid-template-rows'</h3>
<pre class='propdef partial'>
Name: grid-template-columns, grid-template-rows
New values: masonry
Initial: none
Applies to: [=grid containers=]
Inherited: no
Percentages: refer to corresponding dimension of the content area
Computed value: the keyword ''grid-template-columns/none'' or the keyword ''grid-template-columns/masonry'' or a [[computed track list]]
Animation type: see [[css-grid-2#track-sizing|CSS Grid Level 2]]
</pre>
[=Masonry layout=] can be applied to [=grid containers=]
by specifying the value ''grid-template-columns/masonry'' for one of its axes,
defining it as the [=stacking axis=].
Such [=grid containers=] are called [=masonry containers=].
If ''grid-template-columns/masonry'' is specified
for both ''grid-template-columns'' and ''grid-template-rows'',
then the [=used value=] for ''grid-template-columns'' is ''grid-template-columns/none'',
and thus the [=inline axis=] will be the [=grid axis=].
<h4 id="grid-auto-flow">
Auto Flow Directions: the 'grid-auto-flow' property</h4>
<pre class='propdef'>
Name: grid-auto-flow
Value: [ row | column | row-reverse | column-reverse ] || dense || wrap-reverse
Initial: row
Applies to: <a>grid containers</a>
Inherited: no
Percentages: n/a
Computed value: specified keyword(s)
Animation type: discrete
</pre>
<p dfn-for=grid-auto-flow>This specification extends the <a href="https://www.w3.org/TR/css-grid-2/#grid-auto-flow-property">grid-auto-flow</a> property to add
<dfn value>row-reverse</dfn>,
<dfn value>column-reverse</dfn>,
and
<dfn value>wrap-reverse</dfn>,
which reverse the directions of the [=grid item placement algorithm=].
In [=masonry layout=], the flow axis specified by ''grid-auto-flow'' is ignored:
items are always placed by filling across the [=grid axis=].
ISSUE: Should that be the case, or should we follow the 'grid-auto-flow' axis always
(so it would fill similar to flexbox, but with explicitly-sized tracks)?
ISSUE(9326):
Should <css>dense</css> packing apply to masonry?
It's much more expensive in masonry,
as you have to lay out the element in every possible gap spot
to see if it's short enough to fit;
Grid gets to just juggle some integers.
</section>
<section class="option masonry">
<h3 id="masonry-model-masonry-option">
<span class="option masonry">Grid-independent Option:</span> Establishing Masonry Layout</h3>
<h4 id="masonry-display">
Establishing Masonry Containers: the ''masonry'' and ''inline-masonry'' 'display' values</h4>
<pre class="propdef partial">
Name: display
New values: masonry | inline-masonry
</pre>
<dl dfn-type=value dfn-for=display>
: <dfn>masonry</dfn>
:: This value causes an element to generate a [=masonry container=] box
that is [=block-level=] when placed in [=flow layout=].
: <dfn>inline-masonry</dfn>
:: This value causes an element to generate a [=masonry container=] box
that is [=inline-level=] when placed in [=flow layout=].
</dl>
<h4 id=masonry-direction>
Masonry Track Direction: the 'masonry-direction' property</h4>
<pre class=propdef>
Name: masonry-direction
Value: row | column | row-reverse | column-reverse
Initial: column
Inherited: no
Applies to: [=masonry containers=]
Computed value: as specified
Animation type: discrete
</pre>
The 'masonry-direction' property
specifies how items are placed
in the [=masonry container=],
by setting its [=stacking axis=] and direction.
<dl dfn-type=value dfn-for=masonry-direction>
: <dfn>column</dfn>
:: The [=masonry container's=] [=stacking axis=] is its [=block axis=],
and masonry layout starts from its [=block-start=] edge.
: <dfn>column-reverse</dfn>
:: The [=masonry container's=] [=stacking axis=] is its [=block axis=],
and masonry layout starts from its [=block-end=] edge.
: <dfn>row</dfn>
:: The [=masonry container's=] [=stacking axis=] is its [=inline axis=],
and masonry layout starts from its [=inline-start=] edge.
: <dfn>row-reverse</dfn>
:: The [=masonry container's=] [=stacking axis=] is its [=inline axis=],
and masonry layout starts from its [=inline-end=] edge.
</dl>
The [=masonry container's=] [=grid axis=]
is perpendicular to its [=stacking axis=].
<h4 id=masonry-fill>
Masonry Cross Direction: the 'masonry-fill' property</h4>
<pre class=propdef>
Name: masonry-fill
Value: normal | reverse
Initial: normal
Inherited: no
Applies to: [=masonry containers=]
Computed value: as specified
Animation type: discrete
</pre>
'masonry-fill' determines what direction auto-placed items are laid out in
when multiple tracks are tied for “shortest”.
<dl dfn-for=masonry-fill dfn-type=value>
: <dfn>normal</dfn>
::
Ties are broken
by filling the startmost track
: <dfn>reverse</dfn>
::
Ties are broken
by filling the endmost track.
</dl>
<h4 id=masonry-flow>
Masonry Flow Directions: the 'masonry-flow' shorthand</h4>
<pre class="propdef shorthand">
Name: masonry-flow
Value: <<'masonry-direction'>> || <<'masonry-fill'>>
</pre>
The 'masonry-flow' property is a [=shorthand=]
for the 'masonry-direction' and 'masonry-fill' properties.
<h4 id=masonry-shorthand>
Masonry Definition Shorthand: the 'masonry' property</h4>
<pre class="propdef shorthand">
Name: masonry
Value: <<'masonry-template-areas'>> || <<'masonry-template-tracks'>> || <<'masonry-direction'>> || <<'masonry-fill'>>
</pre>
The 'masonry' shorthand sets
'masonry-template-areas',
'masonry-template-tracks',
'masonry-direction',
and 'masonry-fill' at the same time.
</section>
<h2 id="masonry-track-templates">
Masonry Track Specification</h3>
In the [=grid axis=],
the full power of [=grid layout=] is available for track specification:
* Track sizes, line names, and areas can be specified on the [=masonry container=]’s [=grid axis=],
just like in [=grid layout=].
* The [=explicit grid=] and [=implicit grid=] are formed in the same way as for a regular [=grid container=].
* Items can be [[#masonry-track-placement|placed]] against these grid templates just as in [=grid layout=].
However,
auto-placed items contribute sizing to all tracks,
not just the track into which they are ultimately placed;
see [[#track-sizing]].
Note: This is because auto-placed items must be laid out <em>as</em> they are placed,
so that each track knows how “full” it is
(and therefore which track should receive the next auto-placed item);
thus, the tracks themselves must already have a definite size
so that the items know their [=available space=] during layout.
<section class="option grid">
<h3 id="masonry-track-grid-option">
<span class="option grid">Grid-integrated Option:</span> Declaring Masonry Track Templates: the 'grid-template-*' properties</h3>
The 'grid-template-*' and 'grid-auto-rows'/'grid-auto-columns' properties
(and their shorthands)
apply in the [=grid axis=] of the [=masonry container=]
and establish tracks just as on regular [=grid containers=].
ISSUE(10869): What should be the initial track listing?
</section>
<section class="option masonry">
<h3 id="masonry-track-masonry-option">
<span class="option masonry">Grid-independent Option:</span> Declaring Masonry Track Templates: the 'masonry-template-*' properties</h3>
Tracks in the [=grid axis=] of a [=masonry container=]
are established with 'masonry-template-tracks',
'masonry-template-areas',
and 'masonry-auto-tracks'.
<pre class=propdef>
Name: masonry-template-tracks
Value: <<'grid-template-columns'>>
Initial: repeat(auto-areas, auto)
Applies to: [=masonry containers=]
Inherited: no
Percentages: refer to correspodning dimension of the content area
Computed value: by computed value type per item in the [=computed track list=]
Animation type: if list lengths match, by [=computed value=] type; otherwise, discrete
</pre>
'masonry-template-tracks' has the same syntax and interpretation as 'grid-template-columns',
but a different initial value.
(Instead of defaulting to no tracks, as in Grid Layout,
it defaults to matching 'masonry-template-areas', if possible,
or otherwise filling the [=masonry container=]
with as many ''grid-template-columns/auto'' tracks as possible.)
ISSUE(10869): What should be the initial value?
<pre class=propdef>
Name: masonry-template-areas
Value: none | <<string>>
Initial: none
Applies to: [=masonry containers=]
Inherited: no
Percentages: n/a
Computed Value: the keyword ''masonry-template-values/none'' or a string
Canonical Order: per grammar
Animation type: discrete
</pre>
'masonry-template-areas' has the same syntax and interpretation as 'grid-template-areas',
except it only takes a single string defining one "row" of area names.
<pre class=propdef>
Name: masonry-auto-tracks
Value: <<'grid-auto-columns'>>
Initial: auto
Applies to: grid containers
Inherited: no
Percentages: refer to correspodning dimension of the content area
Computed value: a [=computed track list=]
Canonical order: per grammar
Animation type: if the list lengths match, by computed value type per item; discrete otherwise
</pre>
'masonry-auto-tracks' has the same syntax and interpretation as 'grid-auto-columns'.
</section>
<h3 id="subgrids">
Subgrids</h3>
[=Subgridding=] allows nested [=masonry containers=] (and [=grid containers=])
to share track sizes.
If the parent's corresponding axis is a [=grid axis=],
the subgridded axis is taken from the parent container
[[css-grid-2#subgrids|as specified for grid containers]];
if the parent's corresponding axis is a [=stacking axis=]...
<section class="option grid">
<span class="option grid">Grid-integrated Syntax:</span>
...the subgridded axis acts like ''masonry''.
Note: If this results in ''grid-template/masonry'' in both axes,
it is resolved as normal for [=masonry containers=] with double-axis ''grid-template/masonry'' templates,
i.e. it acts like ''grid-template-columns: none; grid-template-rows: masonry''.
</section>
<p class="option masonry"><span class="option masonry">Grid-independent Syntax:</span>
...the subgridded axis acts like ''grid-template/none''.
In [=masonry layout=], auto-placed [=subgrids=]
don't inherit any line names from their parent grid,
because that would make the placement of the item
dependent on layout results;
but the subgrid's tracks are still aligned to the parent's tracks as usual.
<div class="example">
Here's a subgrid <a href="examples/subgrid-example-1.html">example</a>:
```css
<style>
.grid {
display: inline-grid;
grid: auto auto 100px / masonry;
align-content: center;
height: 300px;
border: 1px solid;
}
.grid > * {
margin: 5px;
background: silver;
}
.grid > :nth-child(2n) {
background: pink;
}
.grid subgrid {
display: grid;
grid: subgrid / subgrid;
grid-row: 2 / span 2;
grid-gap: 30px;
}
.grid subgrid > * { background: cyan; }
</style>
```
```html
<div class="grid">
<item>1</item>
<item>2</item>
<item>3</item>
<subgrid>
<item style="height:100px">subgrid.1</item>
<item>sub.2</item>
<item>s.3</item>
</subgrid>
<item>4</item>
<item>5</item>
<item style="width: 80px">6</item>
<item>7</item>
</div>
```
<figure>
<img src="images/subgrid-example-1.png">
<figcaption>
The rendering of the subgrid example above.
</figcaption>
</figure>
Note how the subgrid's first item ("subgrid.1") contributes
to the intrinsic size of the 2nd row in the parent grid.
This is possible since the subgrid specified a definite position
so we know which tracks it will occupy.
Note also that trying to subgrid the parent's [=stacking axis=]
results in the subgrid getting [=masonry layout=] in its [=inline axis=].
</div>
A [=subgrid=] that is a [=masonry container=]
can be referred to as a <dfn export>submasonry</dfn>.
<h3 id="repeat-notation">
Track Repetition: the ''repeat()'' notation</h3>
This specification introduces new keywords and masonry-specific behavior
for the ''repeat()'' notation.
<h4 id="repeat-auto-areas">
repeat(auto-areas)</h3>
The new <dfn value for="repeat()">auto-areas</dfn> value for the ''repeat()'' notation
represents the number of repetitions necessary
for the total number of explicit tracks to match
the 'grid-template-areas' / 'masonry-template-areas' value
in effect in the corresponding axis.
If multiple tracks are listed for the repetition,
the final repetition is truncated as necessary
to produce the correct number of tracks.
Note: Unlike ''repeat()/auto-fill''--
which always repeats at least once and always repeats the track listing entirely--
the number of repetitions for ''repeat()/auto-areas'' can be zero
(if there are already enough explicit tracks),
and the final repetition can be partial.
If 'grid-template-areas' / 'masonry-template-areas' is ''grid-template-areas/none'',
this value behaves as ''auto-fill''.
Note: This value applies both to regular [=grid containers=] and to [=masonry containers=].
ISSUE(10854): It's unclear if we actually need this value.
<h4 id="repeat-auto-fit">
repeat(auto-fit)</h3>
In [=masonry containers=] (as in regular [=grid containers=])
''repeat()/auto-fit'' acts like ''repeat()/auto-fill'',
but with empty tracks [=collapsed tracks|collapsed=].
However, because placement occurs after track sizing,
[=masonry containers=] use a heuristic
to determine if a track will be occupied:
* All tracks occupied by explicitly placed items are considered occupied.
* With the sum of the spans of all auto-placed items as <var>N</var>,
all unoccupied tracks up to the <var>N</var>th such track
are considered occupied.
All tracks produced by the ''repeat()/auto-fit'' repetition and considered unoccupied by this heuristic
are assumed “empty” and are [=collapsed tracks|collapsed=].
A [=collapsed track=] cannot accept placement of auto-placed items.
Note: It is possible for an auto-placed item to be placed in a track when ''repeat()/auto-fill'' is used
that would be collapsed if ''repeat()/auto-fit'' is used
if there are auto-placed items with a span greater than 1
mixed with explicitly-placed items that leave gaps too small for the auto-placed items.
<h3 id="track-sizing">
Grid Axis Track Sizing</h3>
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 with an [=automatic grid position=] contribute
(regardless of whether they are ultimately placed in that track).
<div class="example">
For example, suppose there are two columns in the [=grid axis=]
and that
* Items A, B, and C have no explicit position.
* Item D is explicitly placed into the first column.
In this case, items A, B, C, and D all contribute to sizing the first column,
while only A, B, and C (and not D) contribute to the second column.
</div>
In the case of spanning items with an [=automatic grid position=],
they are assumed to be placed at every possible start position,
and contribute accordingly.
<div class="example">
For example, suppose there are 5 columns in the [=grid axis=],
with the middle having a fixed size of ''100px''
and the other two being ''grid-template/auto''-sized.
For the purpose of track sizing,
an item that spans 2 tracks
and has an intrinsic contribution of 220px
is essentially copied and assumed to exist:
* At grid line 1,
contributing 110px to each of the first two tracks.
* At grid line 2,
contributing 120px to the second track.
* At grid line 3,
contributing 120px to the fourth track.
* At grid line 4,
contributing 110px to the fourth and fifth tracks.
</div>
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="track-sizing-subgrid">
Subgrid Item Contributions</h4>
When sizing the tracks of either a regular [=grid container=] or a [=masonry container=],
a [=submasonry=] has special handling of items that have an [=automatic grid position=]:
* Any such item is placed into every possible grid track
that could be spanned by the [=submasonry=].
(If the submasonry has a [=definite grid position=], thus only the spanned tracks;
if it has an [=automatic grid position=], then all tracks in the parent grid.)
* Any such item receives the largest margin/border/padding contribution
of each edge at which it could hypothetically be placed.
If the item spans the entire subgrid, it receives both.
(See <a href="https://www.w3.org/TR/css-grid-2/#subgrid-item-contribution">CSS Grid Layout §9</a>.)
<h4 id="track-sizing-performance">
Optimized Track Sizing</h4>
Track sizing can be optimized by aggregating items
that have the same span size and placement
into a single virtual item
as follows:
<ol>
<li>
Separate all the [=masonry items=] into <dfn>item groups</dfn>, according to the following properties:
* the span of the item
* the placement of the item,
i.e. which tracks it is allowed to be placed in
* the item's [=baseline-sharing group=]
Note: For example, an item with span 2 placed in the second track
will be in a different group than an item with span 2 that has an [=automatic grid position=].
<li>
For each [=item group=], synthesize a <dfn>virtual masonry item</dfn>
that has the maximum of every intrinsic size contribution
among the items in that group.
If the items apply [=baseline alignment=],
determine the baselines of the [=virtual masonry item=]
by placing all of its items into a single hypothetical grid track
and finding their shared baseline(s) and shims.
Increase the group's intrinsic size contributions accordingly.
<li>
Place hypothetical copies of each [=virtual masonry item=] into the [=grid axis=] tracks
in every position that the item could potentially occupy,
and run the [[css-grid-2#algo-track-sizing|track sizing algorithm]] with those items.
The resulting track sizes are the [=masonry container's=] track sizes.
</ol>
Note: This optimization should give the same results
as the track sizing description [[#track-sizing|above]];
if not this is an error, please
<a href="https://github.com/w3c/csswg-drafts/issues">report it to the CSSWG</a>.
<h2 id="masonry-track-placement">
Masonry Placement</h3>
In the [=grid axis=],
items can be <em>explicitly placed</em> into tracks and span them using the familiar [=grid-placement properties=]’ syntax.
Auto-placement, however, uses the [[#masonry-layout-algorithm]],
placing each item with an [=automatic grid position=]
into the “shortest” masonry track available.
<div class="example">
Here's a masonry layout <a href="examples/pinterest-with-span.html">example</a>
demonstrating placed and spanning items:
<figure>
<img src="images/example-pinterest-with-span.png">
<figcaption>Rendering of the example above.</figcaption>
</figure>
ISSUE: Need a better example!!!
</div>
<section class="option grid">
<h3 id="masonry-placement-grid-option">
<span class="option grid">Grid-integrated Option:</span> Specifying Masonry Item Placement: the 'grid-column-*' and 'grid-row-*' properties</h3>
The 'grid-column-*' and 'grid-row-*' properties
(and their shorthands)
apply in the [=grid axis=] of the items
and establish placement just as in regular [=grid layout=].
</section>
<section class="option masonry">
<h3 id="masonry-placement-masonry-option">
<span class="option masonry">Grid-independent Option:</span> Specifying Masonry Item Placement: the 'masonry-track-*' properties</h3>
Item placement in the [=grid axis=] of a [=masonry container=]
is established with the
<dfn property>masonry-track-start</dfn> and
<dfn property>masonry-track-end</dfn> properties
(and their <dfn property>masonry-track</dfn> shorthand),
whose syntax and interpretation are analogous to the
'grid-column-start' and 'grid-column-end' properties
(and their 'grid-column' shorthand).
</section>
<h3 id="masonry-slack">
Placement Precision: the 'masonry-slack' property</h3>
<pre class=propdef>
Name: masonry-slack
Value: <<length-percentage>>
Initial: 1em
Percentages: relative to the [=grid-axis=] [=content box=] size of the [=masonry container=]
Inherited: no
Applies to: [=masonry containers=]
Computed value: a computed length
Animation type: discrete
</pre>
[=Masonry containers=] are filled
by placing each [=masonry item=]
in whichever [=masonry track=] is currently the least filled.
When multiple tracks are tied for least-filled,
placing the items in order looks good.
But if tracks are only <em>very slightly</em> different heights,
it can look strange to have them not fill in order,
as the height differences aren't perceived as <em>meaningfully</em> different.
The 'masonry-slack' property specifies what the threshold is
for considering tracks to be “the same height”,
causing them to fill in order.
<dl dfn-type=value dfn-for=masonry-slack>
: <dfn><<length>></dfn>
:: Specifies the <dfn dfn for=masonry>tie threshold</dfn>
for the [=masonry container=].
Placement positions are considered to be equally good (“tied”)
if they are within the specified distance
from the shortest position.
Note: The initial value is a “small” distance (''1em'')
that is probably appropriate to represent “close enough”.
</dl>
Issue: Is ''1em'' the right default?
<h3 id="masonry-layout-algorithm">
Masonry Layout and Placement Algorithm</h3>
For each of the tracks in the [=grid axis=],
keep a <dfn>running position</dfn> initialized to zero.
Maintain also a <dfn>auto-placement cursor</dfn>,
initially pointing to the first line.
For each item in [=order-modified document order=]:
<ol>
<li>
If the item has a [=definite grid position=] in the [=grid axis=],
use that placement.
ISSUE: Should this also update the placement cursor?
Otherwise, resolve its [=grid axis=] placement using these substeps:
<ol>
<li>Starting at the first [=grid axis=] line in the [=implicit grid=],
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 <var>max_pos</var>.
<li>Increment the line number and repeat step 2
until the item would no longer fit inside the grid.
<li>Let |possible lines| be the line that resulted in the smallest <var>max_pos</var>,
and all lines that result in a <var>max_pos</var> within the [=tie threshold=] of this <var>max_pos</var>.
<li>Choose the first line in |possible lines| greater than or equal to the [=auto-placement cursor=]
as the item's position in the [=grid axis=];
or if there are none such, choose the first one.
<li>Update the [=auto-placement cursor=] to point to item's last line.
</ol>