From lesson 6-1, justify-content aligns flex items along the main axis.
| Property | Axis |
|---|---|
justify-content | main, always |
align-items | cross |
That model stays useful here, because grid reuses the idea while controlling two axes at once.
Rows and columns at once
Any app used daily, whether a photo gallery, a dashboard of stat cards, or a page with a sidebar, is rows and columns that stay aligned with each other. Flexbox lays items out along one axis, so aligning across rows required hacks. Grid controls two.
.gallery {
display: grid;
grid-template-columns: 200px 1fr 1fr;
gap: 16px;
}| Track value | Meaning |
|---|---|
200px | a fixed column |
1fr | one fraction of the free space |
2fr | twice the share of a 1fr track |
grid-template-columns defines the column tracks, here a fixed 200px column followed by two flexible ones.
fr is a new unit meaning one fraction of the free space, so 1fr 1fr splits the leftover equally and 2fr 1fr splits it 2 to 1, just as flex-grow did in lesson 6-2.
Children fill the cells automatically, left to right, wrapping into new rows as needed. The shorthand typed constantly is grid-template-columns: repeat(3, 1fr);, which makes three equal columns.
Spanning and placing
Any grid child can claim more than one cell.
.featured {
grid-column: 1 / 3; /* start at line 1, end at line 3: spans 2 columns */
}
.sidebar {
grid-row: 1 / 4; /* spans 3 rows */
}Grid counts the lines between tracks, starting at 1, so three columns have four lines.
| Tracks | Lines | 1 / 3 spans |
|---|---|---|
| 3 columns | 4 | the first two columns |
| 3 rows | 4 | the first two rows |
So grid-column: 1 / 3 reads as start at line 1 and end at line 3, which is two tracks rather than three.
Choosing between the two tools is straightforward. Grid handles the page-level skeleton, meaning header, sidebar, content, and galleries, and flexbox handles one-dimensional rows inside it, meaning navbars, button groups, and card internals.
They compose, since a grid cell often contains a flex container, exactly like the header from lesson 6-3.
Splitting free space between fr tracks
With grid-template-columns: 1fr 2fr and 300px of free space, the second column is 200px.
The free space splits into 1 + 2 = 3 shares of 100px each, and the second column takes 2 shares.
| Track | Shares | Width |
|---|---|---|
1fr | 1 | 100px |
2fr | 2 | 200px |
The arithmetic is always the same, namely total shares first, then one share, then each track. Fixed tracks are subtracted before any of this, which is why a 200px 1fr 1fr grid divides only what remains after the fixed column.
A gallery with one wide tile
Three equal columns, plus a single item that opts out of the pattern to span two of them.
CSS
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.featured {
grid-column: 1 / 3;
}
.tile {
background: #d4af37;
border-radius: 8px;
min-height: 90px;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
font-size: 1.5rem;
}| Declaration | Level | Effect |
|---|---|---|
repeat(3, 1fr) | container | three equal fraction columns |
gap: 12px | container | space between cells |
grid-column: 1 / 3 | one item | spans the first two columns |
repeat(3, 1fr) is the shorthand for three equal fraction columns, and grid-column counts lines rather than tracks, so 1 / 3 spans the first two columns.
The tiles are themselves flex containers, centering their own labels. That is the grid-plus-flex composition in a single short stylesheet.
The fraction unit
The unit meaning one share of a grid's free space is fr, the fraction unit.
After fixed tracks take their space, the remaining free space is divided among fr tracks in proportion to their numbers.
| Template | Fixed | Free space split |
|---|---|---|
200px 1fr 1fr | 200px | equally in two |
1fr 2fr | none | 1 to 2 |
The first row is the example from earlier in the lesson. Because fr describes a share rather than a size, a grid built from it never overflows the way a row of fixed pixel widths eventually does.