DEV Community

Cover image for How to setup a layout with CSS Grid
Stephen Collins
Stephen Collins

Posted on • Updated on

How to setup a layout with CSS Grid

Table of Contents

  1. Introduction
  2. How to create a CSS Grid container
  3. How to use CSS Grid template areas
  4. How to use CSS media queries with CSS Grid template areas
  5. Conclusion

Introduction

In this blog post, we are going to explain how to setup a simple, responsive web layout with CSS Grid and minimal layout CSS.

The topics we are going over include how to create a CSS Grid container, how to use CSS Grid template areas, and how to use CSS media queries with CSS Grid template areas - for building the responsiveness we are looking for, both simply and declaratively. This is the CodePen with the finished code we are going to be building in this tutorial blog post. Here's what it will look like:

Basic CSS Grid layout image

and on smaller screens:

Basic CSS Grid layout image on mobile

How to create a CSS Grid container

First up, we need to create a CSS Grid container. This is pretty easy to do, just set the display property of a CSS selector (like CSS classes) on our root element of our layout, like so:

.home-content {
  display: grid;
}
Enter fullscreen mode Exit fullscreen mode

At this point, and to expand our our layout to fill the parent (in this case, the body of the HTML5 document), our home-content class (our root layout CSS class) and our body CSS selector should look like this:

body {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  height: 100vh;
  width: 100vw;
}

.home-content {
  display: grid;
  width: inherit;
  height: inherit;
}
Enter fullscreen mode Exit fullscreen mode

The HTML we are working with for this tutorial is entirely just this:

<div class="home-content">
  <div class="line-1"></div>
  <div class="bar-0"></div>
  <div class="line-0"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Pro tip: the body element is the root element of the content of the document (not discussing the head element here), so if we set it to have 0 margin and 0 padding (margin is outside of an element's border, padding is inside an element's border by the way), with box-sizing (for good practice) set to border-box, we can set the body to have a width of 100vw and a height to 100vh and we will completely, perfectly fill the viewport without any awkward scroll. And, if we set the home-content class to inherit the width and height of it's parent, our root layout element will completely fill the viewport (the "stuff" you see in the browser outside of the browser's UI).

With our root layout element CSS set, we can move on to how we can describe our layout with CSS Grid template areas.

How to use CSS Grid template areas

First, we'll share the code, then break it down:

.bar-0 {
  grid-area: bar-0;
  background: green;
  /* just so this grid child doesn't shrink too much*/
  min-width: 400px;
}

.line-0 {
  grid-area: line-0;
  background: orange;
}

.line-1 {
  grid-area: line-1;
  background: skyblue;
}

.home-content {
  display: grid;
  width: inherit;
  height: inherit;
  grid-template-columns: 3fr 1fr;
  grid-template-rows: repeat(10, 1fr);
  grid-template-areas:
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-1 bar-0"
    "line-1 bar-0"
    "line-1 ."
    "line-1 ."
    "line-1 .";
}

/* added for minimal polish of this codepen. Not important for the layout itself */
.home-content > div {
  margin: 0.5em;
  border-radius: 8px;
}
Enter fullscreen mode Exit fullscreen mode

Let's explain what we are doing with the line-0, line-1, and bar-0 CSS classes. The CSS Grid-related property we've added is called grid-area. What we are doing specifically here with grid-area is to name the particular CSS class as a CSS Grid area to let us then reference (for responsive positioning) in our parent grid (the home-content class). We can accomplish this referencing through the use of the grid-template-areas CSS grid property in our home-content CSS class.

The grid-template-areas property is what let's us "declaratively" describe what we want our layout to look like. Before we can get our CSS Grid to layout as we intend, we have to tell CSS Grid how to create the columns and rows of our grid. We can use grid-template-columns to create our grid's columns, and grid-template-rows to create our grid's rows, using generally either exact pixel units or a newer, more flexible unit called "fr", which represents a fraction of the leftover space in the grid container. So, in our home-content class below:

.home-content {
  display: grid;
  /* ... */
  grid-template-columns: 3fr 1fr;
  grid-template-rows: repeat(10, 1fr);
  /* ... */
}
Enter fullscreen mode Exit fullscreen mode

What we are saying for our columns with the grid-template-columns property, is that we want our first column (the 3fr number) to be three times larger than our second column (the 1fr number), and we want both columns to expand to the full width of our grid container ("proportionally" expand on a 3-to-1 basis).

For our rows with the grid-template-rows, we state that we want ten rows each exactly equal to 1fr. The repeat function is a nice convenience over typing out 1fr ten times manually. The reason we are using a high number of rows here is to create the layout that's impossible with Flexbox without special, specific child class CSS or creating additional elements: in a single CSS Grid property, we can create an "uneven" yet responsive element (our bar-0 div). Our bar-0 grid area "overlaps" an imaginary horizontal cross-section between the line-0 and line-1 divs. We can now define our entire grid layout with the grid-template-areas CSS property like below:

.home-content {
  display: grid;
  width: inherit;
  height: inherit;
  grid-template-columns: 3fr 1fr;
  grid-template-rows: repeat(10, 1fr);
  grid-template-areas:
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-0 bar-0"
    "line-1 bar-0"
    "line-1 bar-0"
    "line-1 ."
    "line-1 ."
    "line-1 .";
}
Enter fullscreen mode Exit fullscreen mode

As an aside, something to mention here about the dot, "." inside our grid-template-areas property. In order for our grid-template-areas to match up according to our grid-template-rows and grid-template-columns specifications, we need to have exactly 2 rows of 10 columns fully defined, but we want the bar-0 to "exactly overhang" by "3" fr units. So we use the dot, "." to designate "hard stops" between cells. The net effect is to keep our grid sized as expected as well as for CSS Grid to know how to "responsively" handle the empty space of the last three cells at the bottom right of our grid. Try removing the dots on the CodePen; you'll see that the layout breaks.

This layout above looks pretty good on larger screens, but what about smaller screens, where multiple columns of content generally look bad? That's where we can use CSS media queries with CSS Grid.

How to use CSS media queries with CSS Grid template areas

The general best practice for building responsive layouts is to define your smallest layout first (for the smallest screen sizes you will support), then use CSS media queries to re-define your major layout-controlling containers to (typically) expand to fill the additional space offered by larger screens. This often means things like allowing content to take up space horizontally, as well as vertically, rather than focusing on a vertically-oriented content for smaller screens like mobile phones.

So, for our grid-based layout, all we are going to do is define our smallest layout outside of any CSS media query first, and then define our multi-column layout for larger screens inside a single CSS media query (with a minimum screen width just set to 900px):

/* vertical-oriented layout suitable for smaller screens */
.home-content {
  display: grid;
  width: inherit;
  height: inherit;
  grid-template-columns: 1fr;
  grid-template-rows: repeat(3, 1fr);
  grid-template-areas:
    "line-0"
    "line-1"
    "bar-0";
}

/* taking advantage of larger screen real estate to add another column */
@media screen and (min-width: 900px) {
  .home-content {
    display: grid;
    width: inherit;
    height: inherit;
    grid-template-columns: 3fr 1fr;
    grid-template-rows: repeat(10, 1fr);
    grid-template-areas:
      "line-0 bar-0"
      "line-0 bar-0"
      "line-0 bar-0"
      "line-0 bar-0"
      "line-0 bar-0"
      "line-1 bar-0"
      "line-1 bar-0"
      "line-1 ."
      "line-1 ."
      "line-1 .";
  }
}
Enter fullscreen mode Exit fullscreen mode

This works because of how cascading works in CSS. In our CSS, once the user's screen is at least 900px wide, our CSS media query will become "activated" and since the home-content rule inside the CSS media query, defined after our mobile layout home-content CSS class definition, the later CSS class definition (in our media query) will take precedence and override our mobile-oriented layout for targeting larger screens.

Conclusion

In this blog post we've explained how to setup a simple web layout with CSS Grid using grid template areas. The complete layout can be found in the CodePen we made for this blog post. Hope you found it helpful! Feel free to share and connect with me on Twitter.

Top comments (0)