-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgrid.css
More file actions
312 lines (264 loc) · 12.7 KB
/
Copy pathgrid.css
File metadata and controls
312 lines (264 loc) · 12.7 KB
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
/* ==========================================================================
bento-grid-theme / grid layer
--------------------------------------------------------------------------
The choreography. A container, five span utilities, the reflow from a
four-column desktop mosaic to a one-column phone stack, and three named
arrangements you can paste.
This is the file tokens.css cannot be. A gap and a radius are values; a
mosaic that collapses without leaving holes in it is a set of rules about
how those values get placed, and rules do not fit in custom properties.
Every value here is a var() reference to tokens.css, with two exceptions,
both structural rather than visual:
1. The two breakpoints, 640px and 1024px. A media query cannot read a
custom property, so these are literals and there is no way around it.
Checked rather than assumed: a rule inside
@media (min-width: var(--x)) never applies, at any value of --x.
2. The span integers. These are written out, and the honest reason is not
the one an earlier version of this comment gave. It said a token would
have to go through calc() in a context where engines disagree. That was
never measured, and when it was, it turned out to be false:
span calc(1 + 1), span min(2, 4) and span var(--n) all resolve
correctly and produce exactly the width of span 2.
They stay written out because a token would not buy anything. The
column count changes at each breakpoint, so the utilities have to be
redefined per breakpoint whatever the span is written as, and a
variable read inside those blocks would need a different value in each
one. That is the same edit in a less obvious form.
Requires tokens.css. components.css is independent of this file and this
file is independent of components.css: the grid places compartments, the
components dress them. Load them in whichever order suits you.
<link rel="stylesheet" href="tokens/tokens.css" />
<link rel="stylesheet" href="components/components.css" />
<link rel="stylesheet" href="components/grid.css" />
Naming: the span classes read width by height in cells. bn-cell-2x1 is two
columns wide and one row tall. They do not imply the .bn-cell surface class
from components.css, and they are scoped to direct children of .bn-grid, so
a bare <figure> can take a span without taking any dressing.
========================================================================== */
/* ==========================================================================
THE CONTAINER
========================================================================== */
/* The phone case is the base, so no span utility is declared here at all.
That is deliberate rather than lazy. In a one-column grid a leftover
`grid-column: span 2` does not collapse to one column; it makes the grid
generate an implicit second column.
What that costs is quieter than an earlier version of this comment claimed,
and worth stating exactly, because the vague version sends people hunting
the wrong symptom. Measured at 390px with a 14px gap: a one-column grid
holding one spanning child computes its tracks as `376px 0px` rather than
`390px`. The phantom track is zero wide and still takes a gap, so every cell
that is not spanning loses 14px and stops meeting the container's right
edge, while the spanning cell still reaches it. Nothing overflows and the
page does not scroll sideways. The cells simply stop agreeing on where the
page ends, which is the kind of fault that gets blamed on padding for an
hour.
Declaring the spans only inside min-width queries means there is nothing to
unset, so that bug has no way in.
Row height goes to auto here for the same class of reason. A stat cell
pinned to a 176px track at four columns is correctly proportioned; the same
cell full-width on a phone is a short line of text stranded in a tall empty
box. At one column the content sets the height. */
.bn-grid {
display: grid;
grid-template-columns: repeat(var(--bn-cols-sm), minmax(0, 1fr));
grid-auto-rows: auto;
gap: var(--bn-gap-sm);
}
/* A grid item whose content is wider than its track (a code block, a long
unbroken string) will otherwise push that track past 1fr and take the rest
of the row with it. minmax(0, 1fr) above handles the track; this handles the
item sitting in it. */
.bn-grid > * {
min-width: 0;
}
/* Auto-placement leaves a hole when a wide cell does not fit in what is left
of the current row: the cursor moves down and the tail of the old row stays
empty. Dense flow backfills those holes.
The cost is real, which is why this is opt-in rather than the default.
Dense placement changes visual order without changing DOM order, so a
sighted mouse user reads the cells in one sequence and a keyboard or screen
reader user reads them in another. Use it for a gallery whose cells have no
narrative order. Do not use it where cell three is a consequence of cell
two. */
.bn-grid-dense {
grid-auto-flow: dense;
}
/* ==========================================================================
ARRANGEMENTS
--------------------------------------------------------------------------
Three compositions known to reflow without holes, given the cell count each
one names. Put the arrangement class on the container alongside .bn-grid and
the cells need no span classes of their own:
<div class="bn-grid bn-arr-stats-board"> ... seven cells ... </div>
Reading the ledgers: each line is one row and the numbers are the widths of
the cells in it, by child index. A row is whole when its numbers sum to the
column count. Every row in every ledger below sums, at both breakpoints,
which is what "no orphan cells" means in practice.
Add a cell beyond the count an arrangement names and it lands as a plain
1x1 at the end. Usually fine at four columns; usually a half-empty last row
at two. Check the tablet width when you do it.
The arrangements sit above the span utilities on purpose. An arrangement
rule and a `.bn-grid > .bn-cell-*` rule have identical specificity, so
source order decides it, and this order is what lets an explicit class on
one cell override the arrangement around it. Move this block below the
utilities and that escape hatch stops working.
All three are declared once, inside the 640px query, and are correct at
1024px too without being restated. `span 2` means two columns at either
width; what changes underneath is how many columns a row has, which is the
whole trick.
========================================================================== */
/* --------------------------------------------------------------------------
FEATURE WALL, six cells.
A held hero with five supporting claims around it. The arrangement for a
product's what-it-does section.
four columns two columns
[ 1 1 2 2 ] [ 1 1 ]
[ 1 1 3 4 ] [ 1 1 ]
[ 5 5 6 6 ] [ 2 2 ]
[ 3 4 ]
[ 5 5 ]
[ 6 6 ]
-------------------------------------------------------------------------- */
@media (min-width: 640px) {
.bn-arr-feature-wall > :nth-child(1) {
grid-column: span 2;
grid-row: span 2;
}
.bn-arr-feature-wall > :nth-child(2),
.bn-arr-feature-wall > :nth-child(5),
.bn-arr-feature-wall > :nth-child(6) {
grid-column: span 2;
}
}
/* --------------------------------------------------------------------------
STATS BOARD, seven cells.
One headline number and six readings. Cell one is the number the page is
about; the other six are the evidence it is not a fluke.
four columns two columns
[ 1 1 2 3 ] [ 1 1 ]
[ 4 5 6 7 ] [ 2 3 ]
[ 4 5 ]
[ 6 7 ]
-------------------------------------------------------------------------- */
@media (min-width: 640px) {
.bn-arr-stats-board > :nth-child(1) {
grid-column: span 2;
}
}
/* --------------------------------------------------------------------------
PORTFOLIO MOSAIC, six cells.
Mixed heights, which is what stops a gallery reading as a contact sheet.
Two of the six are tall, and they are the two the eye lands on.
four columns two columns
[ 1 1 2 3 ] [ 1 1 ]
[ 1 1 2 4 ] [ 1 1 ]
[ 5 5 6 6 ] [ 2 3 ]
[ 2 4 ]
[ 5 5 ]
[ 6 6 ]
-------------------------------------------------------------------------- */
@media (min-width: 640px) {
.bn-arr-portfolio-mosaic > :nth-child(1) {
grid-column: span 2;
grid-row: span 2;
}
.bn-arr-portfolio-mosaic > :nth-child(2) {
grid-row: span 2;
}
.bn-arr-portfolio-mosaic > :nth-child(5),
.bn-arr-portfolio-mosaic > :nth-child(6) {
grid-column: span 2;
}
}
/* ==========================================================================
SPAN UTILITIES, two columns from 640px
--------------------------------------------------------------------------
The intermediate step, and the one that does the work. Going straight from
four columns to one throws the tablet away; going to two keeps the
composition legible as a composition on the device a bento layout is
checked on last.
Each utility states both axes even where one of them is the default. That
is what makes a span class a complete override of an arrangement rather
than a partial one: put bn-cell-1x1 on the hero of a feature wall and it
becomes a 1x1, rather than a one-row cell that is still two columns wide.
========================================================================== */
@media (min-width: 640px) {
.bn-grid {
grid-template-columns: repeat(var(--bn-cols-md), minmax(0, 1fr));
gap: var(--bn-gap);
/* minmax rather than a flat height. A flat grid-auto-rows gives every row
exactly one track height, and a cell whose content needs more spills out
past its own rounded corner, which is the most common way a bento
layout breaks in the wild. minmax sets a floor and lets the row grow.
Cells that fit still line up, because they all take the floor. */
grid-auto-rows: minmax(var(--bn-row-md), auto);
}
/* Every width above one collapses to the full two columns here. There is no
useful three-quarters cell at two columns: a cell is either half the row
or all of it. */
.bn-grid > .bn-cell-1x1 {
grid-column: span 1;
grid-row: span 1;
}
.bn-grid > .bn-cell-2x1 {
grid-column: span 2;
grid-row: span 1;
}
.bn-grid > .bn-cell-1x2 {
grid-column: span 1;
grid-row: span 2;
}
.bn-grid > .bn-cell-2x2 {
grid-column: span 2;
grid-row: span 2;
}
.bn-grid > .bn-cell-full {
grid-column: 1 / -1;
grid-row: span 1;
}
}
/* ==========================================================================
SPAN UTILITIES, four columns from 1024px
The mosaic.
========================================================================== */
@media (min-width: 1024px) {
.bn-grid {
grid-template-columns: repeat(var(--bn-cols), minmax(0, 1fr));
grid-auto-rows: minmax(var(--bn-row), auto);
}
.bn-grid > .bn-cell-1x1 {
grid-column: span 1;
grid-row: span 1;
}
.bn-grid > .bn-cell-2x1 {
grid-column: span 2;
grid-row: span 1;
}
.bn-grid > .bn-cell-1x2 {
grid-column: span 1;
grid-row: span 2;
}
.bn-grid > .bn-cell-2x2 {
grid-column: span 2;
grid-row: span 2;
}
.bn-grid > .bn-cell-full {
grid-column: 1 / -1;
grid-row: span 1;
}
}
/* ==========================================================================
AUTHORING THE WIDTHS YOURSELF
--------------------------------------------------------------------------
If you are not using an arrangement, one rule keeps the reflow clean:
between any two full-width cells, the widths of the cells in between have
to sum to a whole number of rows at every breakpoint.
At four columns that means runs summing to four: 2+2, 2+1+1, 1+1+1+1. At
two columns every width of two or more has already collapsed to a full row,
so what is left has to pair: 1+1. A run of three 1x1 cells is whole at four
columns and orphaned at two, and it is the most common way a mosaic that
looked finished on a laptop breaks on a tablet.
Heights need no such rule. Auto-placement steps forward past an occupied
cell, so a 1x2 beside a 1x1 gets its second row filled by whatever comes
after it rather than leaving a gap underneath.
========================================================================== */