The CSS Grid Tutorial

The CSS Grid Tutorial

The Complete Guide to Using CSS Grid

CSS Grid is a modern layout system that we can use when laying out pages.

It’s often compared with Flexbox. And whilst they are both excellent systems for working with complex layouts, there is one major difference: CSS Grid works on 2 dimensions (rows and columns), while Flexbox works on a single dimension only (rows or columns).

If you only need to define a layout as a row or a column, then Flexbox will likely suit your needs. When working in both dimensions — it’s time for CSS Grid!

CSS Grid basics

We activate the grid layout by making an HTML element a grid container.

Our HTML:

<div class="grid-container">
  <!-- content -->
</div>

In our CSS, we simply set its display property to grid:

.grid-container {
  display: grid;
}

A grid layout consists of a parent element, with one or more child elements.

There are a set of properties that can be applied to the container element, as well as any child elements (being each individual item in the grid).

Throughout this guide we’ll work with the following code: HTML:

<div class="grid-container">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-item">5</div>
  <div class="grid-item">6</div>
  <div class="grid-item">7</div>
  <div class="grid-item">8</div>
</div>

And our CSS styles:

* {
  font-family: monospace;
  text-align: center;
  font-size: 44px;
}
.grid-container {
  display: grid;
  padding: 30px;
  background-color: seagreen;
  border: 2px solid #000;
}
.grid-container > div {
  background-color: lightblue;
  border: 2px solid #000;
}

Defining Columns & Rows

The most common container properties are grid-template-columns and grid-template-rows. With these properties, we define both the number of columns & rows as well as the width of each.

For example, let’s tell our grid to layout its items (child elements) in 4 columns at 200px wide, and 2 rows with a height of 150px each.

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px 200px;
  grid-template-rows: 150px 150px;
}

Grid-template And lets now make it a smaller 3x3 grid: CSS Grid

Auto dimensions

Often you’ll be working with elements with no fixed size. For example, you could have a fixed navbar followed by a flexible content section, then a fixed footer section. For this we can use auto and the layout will adapt to the size of our content:

.grid-container {
  display: grid;
  grid-template-rows: 50px auto 150px;
}

Adding space between grid items

We can add spacing between grid items using grid-column-gap and/or grid-row-gap: CSS Grid-2 We could also use the shorthand grid-gap to set both at once:

.grid-container {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-template-rows: 100px 50px;
  grid-gap: 25px;
}

Grid item positioning

We can control how much space each grid item takes up in the column or row with the following properties:

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end

Let’s see an example:

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px 200px;
  grid-template-rows: 150px 150px;
}
.grid-item1 {
  grid-column-start: 1;
  grid-column-end: 3;
}
.grid-item6 {
  grid-column-start: 3;
  grid-column-end: 5;
}

Here we’ve added classes to the first & sixth items in our grid.

The numbers correspond to the vertical line separating each column. So by setting grid-column-start to 1 and grid-column-end to 3, we’re telling our element to start at the first line & end at the third.

Similarly, we’ve told our sixth element to start at the 3rd line and end at 5.

This of course also applies to grid-row-start and grid-row-end, with the cells expanding across rows instead of columns.

Item position shorthand

We can repeat the above using the shorthand properties of grid-column & grid-row, like so:

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px 200px;
  grid-template-rows: 150px 150px;
}
.grid-item1 {
  grid-column: 1 / 3;
}
.grid-item6 {
  grid-column: 3 / 5;
}

And we could take this even further by using grid-area as a shorthand for grid-column and grid-row. This would only apply in cases where we need an item to span both rows & columns:

.grid-item1 {
  grid-row: 1 / 4;
  grid-column: 3 / 5;
}

Would become:

.grid-item1 {
  grid-area: 1 / 3 / 4 / 5;
}

With the order being: grid-row-start > grid-column-start > grid-row-end > grid-column-end.

Using 'span' to position items

Another option we have when positioning our items is span:

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px 200px;
  grid-template-rows: 150px 150px;
}
.grid-item1 {
  grid-column: 1 / span 2;
}
.grid-item6 {
  grid-column: 3 / span 2;
}

With grid-column: 1 / span 2 starting at line 1 and spanning across 2 columns.

Using fraction units

One of the great benefits of a grid is the ability to easily create highly flexible layouts.

Fraction units give us the ability to build layouts without needing to specify fixed dimensions.

For example, let's divide a grid into 3 columns of equal width, each taking up 1⁄3 of the available space:

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

Grid-template Too simple!

Using other CSS units

We can use any of the CSS length units. So feel free to use a mix of percentages, pixels, rem, em and fractions:

.grid-container {
  grid-template-columns: 2rem 25% 2fr 1fr
}

Using repeat()

We can use repeat() to specify the number of times a row or column will be repeated, and the length of each.

It’s a handy way to quickly put together a layout & it also reduces lines of code! For example, you could define 3 columns of equal width as follows:

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

Using minmax()

We use minmax() to specify a minimum or maximum width for a grid track.

Let’s say you want a column to be between 100px and 300px, followed by a 1fr column:

.grid-container {
  grid-template-columns: minmax(100px, 300px) 1fr;
}

The value for min has to be smaller than the value for max. And fr units can’t be used for the min value, but they can be used for the max!

By using a 1fr as the max value, you’ll ensure that the track expands and takes up the available space:

.grid-container {   
  grid-template-columns: minmax(250px, 1fr) 1fr;   
}

Used this way, minmax() allows us to create grid tracks that adapt to the available space, but that doesn’t shrink narrower than a specified size.

Now if the browser is resized, the 1st column won’t shrink to less than 250px.

You can also use the auto, min-content, and max-content keywords as the min or max values.

Using justify-content

We use justify-content to align the whole grid inside the container.

There are a number of values we can work with:

  • space-evenly
  • space-around
  • space-between
  • center
  • start
  • end

Keep in mind that the grid width has to be less than the container width for the justify-content to work!

Let’s see an example of each:

.grid-container {
   display: grid;
   justify-content: space-evenly;
}
.grid-container {
   display: grid;
   justify-content: space-around;
}
.grid-container {
   display: grid;
   justify-content: space-between;
}
.grid-container {
   display: grid;
   justify-content: center;
}
.grid-container {
   display: grid;
   justify-content: start;
}
.grid-container {
   display: grid;
   justify-content: end;
}

Using align-content

We use the align-content property to vertically align the whole grid inside the container.

Our grid height needs to be less than the container height for this property to work.

.grid-container {
   display: grid;
   align-content: space-evenly;
}
.grid-container {
   display: grid;
   align-content: space-around;
}
.grid-container {
   display: grid;
   align-content: space-between;
}
.grid-container {
   display: grid;
   align-content: center;
}
.grid-container {
   display: grid;
   align-content: start;
}
.grid-container {
   display: grid;
   align-content: end;
}

Using grid-template-areas

We can use grid-template-areas to define named areas & move them around inside the grid, and also to expand grid items across multiple rows and/or columns.

Let’s use grid-template-areas to build a typical layout with a header up top, a sidebar to the left of the main content, followed by a footer: Grid-template-areas And the code used:

HTML:

<div class="grid-container">
  <main>
    Main
  </main>
  <aside>
    Sidebar
  </aside>
  <footer>
    Footer
  </footer>
  <header>
    Header
  </header>
</div>

CSS:

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px 200px;
  grid-template-rows: 125px 225px;
  grid-template-areas:
    "header header header header"
    "sidebar main main main"
    "footer footer footer footer";
}
main {
  grid-area: main;
}
aside {
  grid-area: sidebar;
}
header {
  grid-area: header;
}
footer {
  grid-area: footer;
}

Notice that despite the header being the last element in our HTML, it’s still at the top of our page. This is because we’ve defined its position in CSS with grid-template-areas using the grid-area property.

Making this responsive

If we want the sidebar to move below our main content on mobile devices, we can easily do so using a media query: @media (max-width: 500px) {

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

Conclusion

If you liked this blog post, follow me on Twitter where I post daily about Tech related things!

🌎 Let's Connect

Did you find this article valuable?

Support Richard Rembert by becoming a sponsor. Any amount is appreciated!