Grid Templates and Item Placement

Grid Anatomy

Before we dive into templates, there are a few terms you should be familiar with when we talk about grids.

  • Grid cells are the singular units created by the rows and columns.
  • Grid lines start from 1 and count the lines dividing grid rows and columns.
  • Grid tracks are the columns and rows between lines where content is placed.
  • Grid areas are regions where content can be placed, which may be a single grid cell or a rectangle of multiple grid cells.
  • grid tracks
  • grid lines
  • grid cell
  • grid area

Planning Your Grid

A really good technique for figuring out how to set up a grid in CSS is to sketch over a mockup of your design. Drawing straight lines (or dropping guides) through the mockup can help you figure out how many columns and rows will be needed.

When planning a grid based layout, it helps to sketch dividing lines and numbers over your design.

Grid Templates

The template defines how many columns (and optionally rows) the grid should have, how big they should be, and whether they have names that we can refer to later.

A lot of times you can set up just the columns, and skip setting rows on your template. This allows the row count and heights to be determined based on the content.

Most of the figures on this page define row heights only for illustration, since there's no actual content in these grids!

.grid-container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-rows: 5em 5em;
}

If you happen to have more items than the number of columns and rows you defined in your template, the grid algorithm will continue adding automatically sized rows or columns until all the elements have been placed on the grid.

Repeat Syntax

If multiple columns or rows are going to be the same size, you can save yourself some typing using the repeat() function. This will pop up again later in the more advanced grid features!

.grid-container {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 5em 5em;
}

Placing Items on The Grid

By default, Grid places one item at a time across each column, wrapping to new rows as needed.

We can let the grid algorithm handle laying out all of our content, or we can explicitly place items on the grid (or both). There are several ways to do this.

For whole-page layouts, the ascii method with named areas is intuitive. For smaller or more abstract grids, you may skip all the naming and just reference grid lines by their numbers. Any method works though, so use whatever makes the most sense to you starting out, and experiment with the others after you've had some practice.

Numbered Lines

Numbered line placement lets you specify a starting line and optionally an ending line. All three of the following examples produce the same output:

.grid-container {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: 5em 5em;
}

.placed-grid-item {
    /* Specify a starting line and an ending line */
    grid-column-start: 2;
    grid-column-end: 5;

    /* Or start / end shorthand. Don't forget spaces around the forward slash! */
    grid-column: 2 / 5;

    /* Or specify a starting point, and how many rows or columns the item should cover. */
    grid-column: 2 / span 3;
}

Named Lines

You can give names to specific grid lines in your template for easier reference later. The names can be anything you want, but if you're defining start and end points, you get some extra perks for using -start and -end in your names.

.grid-container {
    grid-template-columns: 1fr [banner-start] repeat(3, 1fr) [banner-end] 1fr;
    grid-template-rows: 5em 5em;
}

.placed-grid-item {
    grid-column-start: banner-start;
    grid-column-end: banner-end;
}

Named Areas

CSS Grid also has a neat feature that lets you build an ascii diagram for named areas.

.grid-container {
    grid-template-columns: 1fr 4fr;
    grid-template-areas: "header header"
                         "nav    main  "
                         ".      main  "
                         "footer footer";
}

.placed-grid-item {
    grid-area: main;
}

Each unique word becomes a named area that you can place items into. Here I'm using the same names as some of the HTML semantic tags, but you can use any names that make sense for your design.

White space separates columns, so if you want three columns you'll need three words per line. Each string (set of words between quotes) represents a row on the grid. It's probably rare to do this, but you can use dots . to designate blank spaces.

This property is very flexible about letting you use white space in the code to line up your area names. You can put multiple spaces between words to line them up, and the strings do not have to be on separate lines (though it's easier to see that way).

The diagram does not have to be visually proportional to the sizes of your rows and columns in the grid. For example, even if your "nav main" area is by far the tallest portion of the page, you do not need to repeat those areas on multiple lines.

Named areas and the ascii template method are really handy when using media queries. We can redefine the template once, and keep all of the area names on the different grid items. We'll look at this more closely in another demo!

Implicit Naming of Areas and Lines

Grid has one other trick up its sleeve regarding named lines and named areas. When you define a named area (e.g. main), you can also reference its boundary lines using [main-start] and [main-end]. Similarly, if your grid template has lines named [main-start] and [main-end], Grid creates an area called main for you.

This works for both columns and rows. The only catch is you must always use -start and -end when referring to the lines.