[!] [=title "Week 9: Grid 2"] [=content-]

We briefly discussed grids already - we're going to go into more detail on them now. If you haven't, read Grid 1, or you will be very confused.

Note: because this is an incredibly dense bit, there aren't many demos. I highly recommend reading through CSS Grid Layout Guide by CSS-Tricks - it's far more interactive and detailed.

Grid-Template-*

We've already seen the grid-template-columns and grid-template-rows properties: they define the widths of the columns of the grid and the rows of the grid. We're going to go into more detail on how they work now.

First off, the syntax: every use of either property looks like grid-template-dimension: <1> <2> ... <n>;. You can define as many columns as you want, sized however you want! For instance, the magic incantation for "four 50px columns and a fifth which uses up all the remaining space" is simply grid-template-columns: 50px 50px 50px 50px auto;. This is unnecessarily gross, so CSS gives us a useful function: repeat(n, val). This literally just repeats val n times (note: this is not actually universal, it's only for grid). So we can simplify: grid-template-columns: repeat(4, 50px) auto;.

Pixels are bad, because they don't work the same on every screen. A better unit is %. In the context of grid, percent just allocates space remaining along the axis! So for instance, if we want to have 3 thin inner columns and 2 wide outer columns... grid-template-columns: 35% repeat(3, 10%) 35%;. This will always scale the same way for every screen size!

Aside: Percent

At this point everyone should have the mantra "percent means something different in transform than in top" burned into their brains. The CSS percent unit is delicate and complicated! Whenever you use it, be sure you know what it's doing. Because percent means something different in grid-template-columns than in width...

Back on track...

Of course, percentages aren't the only useful tool here. We also have the fr unit! fr essentially allocates space as evenly as possible, but weighted. So for instance, if we want to have 2 columns of the same width, and a third column twice as big as them, grid-template-columns: 1fr 1fr 2fr; will work perfectly. We could manually calculate grid-template-columns: 25% 25% 50%;, but that's bad.

There are also two convenient "sorta-units": min-content and max-content. min-content is always the thinnest the column or row can get before the inner items get too cramped and overflow, and max-content is always the widest the column or row can get before the inner items have "too much" space. This is very nice for goldilocks layouts where you want a column to be "just right" and have the others fit around it! For instance, you might have a 2-panel layout with a thin sidebar (maybe containing links!) and a content block; you could do that with grid-template-columns: max-content auto;.

Grid-Auto-*

Templates are nice, but what if we don't know how much content we have? A good example of this situation is a music player app, where you have nice fancy grid tiles for each song, but you aren't sure how many songs there are. Rather than trying to write an infinitely long grid-template-rows, you can set grid-auto-rows: 50px; almost everything works in grid-auto-rows, with the sole exception of fr (you can still use auto for even distribution).

Whenever the layout engine needs a new row (or column), it will first check if there's a remaining template; and if not, it'll use whatever the grid-auto-* value is.

Grid-Template-Areas

This is the last of the black magic: grid-template-areas and grid-area. Grid-template-areas is a very strange property. It contains arbitrarily many values for rows, and contains strings (in double quotes) describing the area names within columns. For example:

.grid-container {
	grid-template-areas: "b b a"
	                     "b b c"
                             "d d d";
}

This doesn't do much without another tag: grid-area. This is applied to grid cells, not to the grid itself! Say it out loud: grid-area applies to the grid cell, not to the grid container!.

Continuing the example, if we put a few spans defined like so into a grid...

<style>
.grid-container {
	display: grid;
	grid-template-areas: "b b a" /* defines 3 rows and 3 columns with nicely labeled cells */
                             "b b c"
                             "d d d";
	height: 300px;
}
</style>
<div class="grid-container">
	<span style="grid-area: a; background-color: purple;">Area A</span>
	<span style="grid-area: b; background-color: green;">Area B</span>
	<span style="grid-area: c; background-color: orange;">Area C</span>
	<span style="grid-area: d; background-color: red;">Area D</span>
</div>
Area A Area B Area C Area D

Note how, without even having to set a grid-template-rows, we got a decent layout! More importantly, we now have elements spanning across grid lines - there are actually 3 columns and 3 rows, but we only have 4 elements filling them!

grid-template-areas is extraordinarily powerful, and I highly recommend playing with it on your own. Mix it with grid-template-* to control the sizes of your regions!

I strongly recommend everyone practice grids on their own.

[/] [#template.html]