The grid container is the parent element.

The grid items are the child elements (and only the child elements; descendants beyond the children are not grid items).

The child elements of grid items are, well, whatever they may be, they are not children of the main container, so they are not grid items and cannot accept grid properties like their grid item parents.

To create a grid we can use the display: grid property. It can be applied to a series of block elements that normally stack - applying grid-auto-flow: row will make no real visible change to the layout, since its the default, but it can be overridden with grid-auto-flow: column.

Practice site to learn how to play with grid: CSS Grid Garden

Layout

Columns

To have more control over the columns we can say grid-template-columns: <value> <value> <value> where value is the width of each of the specific columns we want to define. This can be in pixels or in fraction units, - a unit specifically used with CSS grid:

.container {
	display: grid;
	grid-template-columns: 2fr 1fr 1fr
}

Note that we can also mix units: 200px 1fr 1fr is valid.

If we have many columns of the same width we can use a function in CSS to shorthand the declaration:

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

More specifically, repeat will follow a pattern. Thus we can say repeat(2, 1fr 2ft) and, assuming 6 columns, it will apply a column width of 1-2-1-2-1-2 (moving excess columns to the second row if necessary).

Rows

To manage rows we can use the grid-auto-rows or grid-template-rows properties. They take arguments similar to those of columns.

A common pattern is to use grid-auto-rows: minmax(<min>, <max>). With this setting, we can specify a minimum height of a row, and we can say auto as a max value, which will allow the rows to grow to a maximum size that will cover the container they are in.

Gaps

We can also add gaps between rows and columns by using row-gap and column-gap respectively, as well as simply gap for both.

Individual items

Assuming we have a .container class that contains 6 separate items, each of them with a .box class, we can select specific ones with pseudo-elements:

.box:first-child {
	background-color: blue;
	grid-column-start: 1;
	grid-column-end: 4;
	grid-row-start: 1;
	grid-row-end: 3;
}

This will cause the first box to span the first three columns. Note that when counting we consider each column to start at the left gutter of that column. This can also be applied to rows.

When thinking about this, starting from column 1 and ending at column 4 effectively means we are taking end minus start columns/rows.

We can shorthand specifying start and ends with the following:

.box:first-child {
	background-color: blue;
	grid-column: 1 / 4;
	grid-row: 1 / 3;
}

We can use the aling-content property to specify where in a given container the content will vertically be displayed. Options such as end and center are common. Likewise we can use justify-content for horizontal movement.

As a shorthand we can say place-content: <align> <justify>. We can also simply say center to apply it to both.

Named grid items

Assuming we have the following HTML, we can define how we want the page to look using grid:

<body>
    <header class="header el"><h1>Header</h1></header>
    <main class="container">
        <div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
        <div class="box">4</div>
        <div class="box">5</div>
        <div class="box">6</div>
    </main>
    <aside class="sidebar el"><h2>Sidebar</h2></aside>
    <footer class="footer el"><h2>Footer</h2></footer>
</body>

In CSS we can use grid-template-areas to define visually the layout as follows:

body {
	display: grid;
	grid-template-columns: repeat(9, 1ft);
	grid-auto-rows: 75px auto 75px;
	grid-template-areas:
		"hd hd hd hd hd hd hd hd hd"
		"mn mn mn mn mn mn mn sb sb"
		"ft ft ft ft ft ft ft ft ft"
}
 
.el {
	background-color: purple;
	color: white;
	display: grid;
	place-content: center;
}
 
.header {
	grid-area: hd;
}
 
.sidebar {
	grid-area: sb;
}
 
.footer {
	grid-area: ft;
}
 
.container {
	grid-area: mn;
}

What this does it defines areas in which each set of grids will be displayed, according to the definition in the body -> grid-template-areas. Note that below the body in the CSS above we have to name each of the elements we want, using grid-area: <name> so that it is applied on the page itself.