As we have seen, flexbox wasn’t designed for grid layouts—but this is where our newest specification is most at home. CSS Grid Layout does exactly what its name suggests: it enables the creation of grid layouts in CSS. This is two-dimensional layout—laying things out as a row and a column at the same time. We’ll go over many more examples of Grid Layout in the rest of this book, but let’s start by seeing how Grid can solve the problem we had with making flexbox display like a grid.

In this example, I’m creating a three-column grid (Fig 3.17). My container has display: grid, and I’ve created three equal-width columns with the grid-template-columns property, plus a new unit created for Grid: a flexible-length unit known as fr. We’ll take a closer look at this unit in Chapter 5; for now, keep in mind that it represents a fraction of the space available in the grid container. With three tracks all set to 1fr each, the available space is divided into three and distributed equally. This is all we need to do to get the direct child of the container to display as a grid. Unlike with flexbox, we don’t need to add any rules to the children; they will just pop themselves into each cell of the grid.

.cards { margin: 0 -10px; display: grid; grid-template-columns: 1fr 1fr 1fr;
}

Code example: http://bkaprt.com/ncl/03-14/



    Screenshot: A 3 column, 2 row grid with 5 card elements. Each element takes a single column and row cell, leaving an empty cell in the right-most column of the second row.

Fig 3.17: The basic grid layout.

As you can see, the items form a strict grid, without us needing to set any widths on them. We can solve another issue that we have with creating a flexbox grid, using properties that are part of the Grid specification. To create gaps between our flex items, in our flexbox example we used margins on the flex items and then needed to add a negative margin on the container to account for the unwanted left and right margin on the far left and right items. CSS Grid Layout includes a grid-gap property to space items out. This property is shorthand for grid-column-gap and grid-row-gap, which can also be specified individually.

To demonstrate how this works, I’ve removed the margins on the items and the negative margin on the container and spaced the items out with grid-gap. You’ll produce the exact same layout as above in the browser, but without the need to mess around with margins and negative margins.

.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px;
}

Code example: http://bkaprt.com/ncl/03-15/

Just as this book was going to print, the CSS Working Group resolved to change the name of the grid-gap properties. grid-column-gap will become column-gap, grid-row-gap will become row-gap, and the grid-gap shorthand will simply be gap. In addition, the definition of these properties has been moved to the Box Alignment Specification. This means that in the future, flexbox may also support gaps in the same way as Grid.

Because browsers have already shipped these properties, they will alias the grid- names to the new names for the foreseeable future. At time of writing, no browser supports the new property names, so I’ve retained the grid- versions in these examples. If you want to be sure of supporting both versions, there’s no reason not to list both in your CSS, as in this example:

.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px; gap: 20px;
}

Positioning items around the grid

We can quickly move away from what flexbox allows us to do by taking advantage of our two-dimensional grid and positioning items on it. The most basic way of doing this is by using line numbers. A grid has numbered grid lines; they start from 1 for both rows and columns. Note that these lines are numbered per the writing mode of the document. Working in English, a left-to-right (LTR) language, column line 1 is on the left-hand side of the grid; row line 1 is at the top. In Arabic, a right-to-left (RTL) language, column line 1 appears on the right of the grid. The far edge of the grid (right in a LTR language and left in a RTL language) is represented by -1.

.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px;
}
.card1 { grid-column: 1 / 3; grid-row: 1;
}
.card2 { grid-column: 3; grid-row: 1;
}
.card3 { grid-column: 1; grid-row: 2 / 4;
}
.card4 { grid-column: 2 / 4; grid-row: 2;
}
.card5 { grid-column: 2 / 4; grid-row: 3;
}

Code example: http://bkaprt.com/ncl/03-16/



    Screenshot: The 3 column, 2 row grid has now become a 3 column, 3 row grid, still with 5 card elements. Card 1 spans the first 2 columns of the first row. Card 2 is in the third column of the first row. Card 3 spans the second and third row of the leftmost column. Card 4 spans the second and third column of the second row, and card 5 spans the second and third column of the third row.

Fig 3.18: Cards placed on the grid by line number.

You can immediately see some of the power of Grid Layout here. We can span columns and rows—something that is hard to do using existing layout methods. The background color of our cards extends to the gutter, even if the content is shorter. It’s also very easy to change how far a block spans—we can even leave white space! If I change the start line of card 3 to row line 3, we get an empty cell (Fig 3.19). Nothing can rise and land in the grid cell; this differs from the behavior of floats, which try to float up and fill the available space.



    Screenshot: The 3 by 3 grid remains similar to figure 3.18. Card 3 no longer spans the second and third row. Instead it is placed in the first column of the third row, leaving a blank space in the first column of the second row.

Fig 3.19: White space made easy with CSS Grid Layout.

Another method of positioning items on a grid involves using named areas. This allows you to describe your layout right in your CSS. To do this with our example, we first give each card a name with the grid-area property. I’m just using letters a through e.

.card1 { grid-area: a; }
.card2 { grid-area: b; }
.card3 { grid-area: c; }
.card4 { grid-area: d; }
.card5 { grid-area: e; }

Next, I add the grid-template-areas property to the container. The value of this property describes what our layout should look like (Fig 3.20).

.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px; grid-template-areas: "a a b" "c d d" "c e e";
}

Code example: http://bkaprt.com/ncl/03-17/



    Screenshot: This grid layout is identical to the 3 by 3 grid from figure 3.18. Cards 1-5 are now represented by named areas a, b, c, d, and e in the same order.

Fig 3.20: The value of grid-template-areas shows visually what our layout looks like.

There are a few things to keep in mind with grid-template-areas. To span across cells, we repeat the name of the area. Card 1 spans across the first two column tracks; thus a is repeated. The areas must be rectangular in nature—we can’t yet create an L-shaped area.

To leave white space, and to leave a cell empty, use a full-stop character. If you replace the first c with ., that cell will remain empty when the layout is created (Fig 3.21).

.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px; grid-template-areas: "a a b" ". d d" "c e e";
}


    Screenshot: This grid layout is identical to the 3 by 3 grid from figure 3.19. Cards 1-5 are now represented by named areas a, b, c, d, and e in the same order. Card 3 (named c) no longer spans the second and third row, but instead only sits in the first column of the third row, leaving a blank space (represented by a full stop in the grid-template-areas) in the first column of the second row.

Fig 3.21: We now have white space left in our layout.

If your grid-area names are longer than one character, you may want to line up the visual rows and columns in the value of grid-template-areas. This is possible because more than one full-stop character can denote an empty cell—if they have no white space between them. You can also add more than one white-space character to space out grid-area names.

This is a very nice way to work with layouts, given how easy it is to move items around. I enjoy working like this during the prototyping stage—rather than worrying about how to achieve layout, I can figure out the best way for my interface to be presented. Then I can go back to the markup to make sure it’s in a logical order based on those decisions.

With these few examples, you already have enough knowledge to start using Grid Layout, and to make decisions about which layout methods to use. There is more to come, but keep in mind that although the specification is large and can do a lot of things, it is very simple at its core. You can do a lot with very little CSS. As you start building layouts, you will have questions, and will want to achieve more with these layout methods. That’s where the rest of this book comes in!