The Matrix of Layout: CSS Grid

I am rebuilding this website with CSS Grid. I was always afraid of doing CSS because in the early days when I learned CSS, there are just too many weird hacks of using tables/float/JavaScript whatever with compromised markup (not semantic) to achieve layout.1

But now in 2019, we have CSS Flexbox and CSS Grid, matured solutions (as of 2017, most browsers shipped native, unprefixed support for CSS Grid) for building grid system! I pick Grid over Flexbox since G comes after F. 2

Study

First off, I read this intro post + A Complete Guide to Grid.

Watched this fantastic video to see it in action.

Miriam is a wizard, thank you so much!

Let me quickly show you how awesome it's:

HTML
<header>
  <h1>header</h1>
</header>
<nav>
  <h2>nav</h2>
  <ul>
    <li>item</li>
    <li>item</li>
    <li>item</li>
  </ul>
</nav>
<main>
  <h2>main</h2>
  <p>
    lorem ipsum...
  </p>
</main>
<footer><h2>footer</h2></footer>
CSS

And some additional colors applied3

body {
  min-height: 100vh;
  display: grid;
  grid-gap: 1em;
  grid: 'header' auto
        'nav' auto
        'main' 1fr
        'footer' auto
      / 1fr;
}

@media (min-width: 40em) {
  body {
    grid: 'header header' auto
          'nav main' 1fr
          'nav footer' auto
        / 12em 1fr;
  }
}

header { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: footer; }
Result

NO MORE HACKS. EVERYTHING LOOKS REASONABLE.

I dont remember how many different hacks could achieve this in early days...

Grid Terminologies

Grid has a lot of settings and they also offer shorthand syntaxes. I suggest do not use shorthand syntax until you‘re familiar, it‘s simialr we first learn how to use margin-top, margin-bottom, margin-left, margin-right. Then after used for a 1000 times. We learned to use margin. Also it hinders yourself when you are learning something new.

Grid has container and its children. Right now settings to grid only applies to direct children until Subgrid support4 kicks in.

To make a container grid:

display: grid | inline-grid;

The children of grid container are called Cells or Grid Items. A horizontal track of cells is called Row, the vertical is called Column. Few cells make up of Areas. The gutter between rows and columns are called row gaps and column gaps respectively.

display: grid

grid-template-columns: 300px 300px 300px;
grid-template-rows: 300px 300px 300px;

column-gap: 30px;
row-gap: 30px;

Too much repeation in grid-template-{columns,rows} so we have repeat():

grid-template-columns: repeat(3, 300px);
grid-template-rows: repeat(3, 300px);

But hey! These size are fixed, we need responsive. We have a new unit called fr, fraction unit:

grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);

Grid Item Size units

fr will divide available spaces in grid container into a fraction.
minmax(min, max) will set grid-item size

grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));

A common problem building a layout is to place multiple items (Instagram photos). For example if we want each photo has same height

We can use the following css to make sure each cell created in the row is of height 300px.

grid-auto-rows: 300px

Placing items

You can see there are lines with number, we can use these grid lines to place items on our gird. You can see I place the <header> element from Column 4th and spans for 18 columns:

grid-column: 4 / span 18;

This is actually a shorthand for:

grid-column-start: 4;
grid-column-end: span 18;

A minus number means placing from the other side, it‘s handy if you want to center things with 4 columns from both ends:

grid-column: 4 / -4;

We can also give grid item names and placing by names grid-area. Or define a visual representation by grid-template-areas

Grid Cells Alignment

justify-items
align-items
place-items

justify-content
align-content
place-content

Grid Item Alignment

justify-self
align-self
place-self

Subgrid?

Only Firefox supports it. You can see what it‘s like from these two videos

Development

Use Firefox. It comes with an awesome CSS Grid debugging tool as of 2019 November 30, that no other browser has something like it. It can show you grid area names, column, and row number.

Example on Firefox of grid area names

Example on Firefox of grid area names

Example on Firefox of 24 grids

Example on Firefox of 24 grids

If you applied a grid container property to a grid item, it will show this has no effect.

Example of Firefox remindering you applying a invalid property

Example of Firefox remindering you applying a invalid property

Properties for Grid Items

Grid Column Starts and Ends

grid-column-start: <number> | <name> | span <number> | span <name> | auto;
  grid-column-end: <number> | <name> | span <number> | span <name> | auto;
Grid Column Syntax
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
header img {
  grid-column: 2 / 6
}

Means header image will be at column 2, extends to column 6.

Grid Row Starts and Ends

grid-row-start: <number> | <name> | span <number> | span <name> | auto;
  grid-row-end: <number> | <name> | span <number> | span <name> | auto;
Grid Row
grid-row: <start-line> / <end-line> | <start-line> / span <value>;

Name a Grid

Name a grid item so it can be referenced in grid-template-areas property.

nav {
  grid-area: nav;
}

Also could be a short hand for grid-row-start + grid-column-start + grid-row-end + grid-column-end:

grid-area: 1 / col4-start / last-line / 6

Alignment of Grid item inside Cell

justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
Properties for Grid Container

Grid Columns and Rows

Defines columns and rows of the grid.

grid-template-columns: <track-size> ... | [<line-name>] <track-size> ...;
grid-template-rows: <track-size> ... | [<line-name>] <track-size> ...;

You can name the grid lines with [<line-name>]:

grid-template-columns: [col0] 40px [col1] 50px;
grid-template-rows: [row0] 25% [row1] 800px [row2] auto;

Grid Gaps

Specifies the size of the grid column/row lines.

grid-column-gap: <size>;
grid-row-gap: <size>;

Shorthand: grid-gap: <grid-row-gap> <grid-column-gap>;

I'm still learning from


I rebuilt this site and please see my Apply CSS Grid post for the learnings.