CSS Grid – The Complete Guide for Designers & Developers

CSS Grid is a module that allows creating a layout based on a grid structure using columns and rows. Until recently, layout in HTML was achieved using floats, tables, and other CSS properties that were not ideal for creating complex page structures.

Then came Flexbox into the world – a kind of system specifically designed to create responsive and robust layouts. Flexbox allows us to align elements and create one-dimensional grids quickly and easily, and currently, it’s the preferred CSS system for most developers.

However, there’s a relatively new player in the neighborhood called CSS Grid and it’s going to revolutionize the way you create layouts, web pages, applications, and user interfaces.

Let’s explain who this new player is and how you can make the most of it…

What is CSS Grid, in essence?

CSS Grid (sometimes simply referred to as Grid for convenience) is a two-dimensional system that enables creating a Grid-based layout. The purpose behind its creation is to simplify the process of creating layouts and complex user interfaces with minimal code hassle.

The central concept behind CSS Grid is a method that allows us to create a structure in the form of a grid defined at the CSS level rather than the HTML level. It helps us create layouts that can be redefined using Media Queries and adapt to different contexts.

Using CSS Grid allows for a separation between the order of elements in HTML and their visual representation on the screen. As designers, this means you’re free to change the position of elements on a page according to various screen sizes without compromising the responsive design structure due to the order of element appearance in HTML markup itself.

It’s quite straightforward to make the Grid fit into the available screen space. Since each element occupies a designated area in the Grid, there’s no risk of elements overlapping due to changes in text size, unexpected content length, and the like.

By the way, CSS has always been there for us in terms of layout and design, but it never did a great job in this context. Initially, we used tables, then floats, followed by inline blocking, and so on. However, these methods were more like workarounds and didn’t offer essential functionality, such as vertical alignment of elements or automatic arrangement of elements within a specific container.

Flexbox greatly helped in these cases when it emerged, but it’s more suitable for one-dimensional layouts, meaning a single row or column, and less suitable for two-dimensional layouts consisting of both columns and rows together.

We’ll explain the intention shortly, so stay with us. In the meantime, let’s summarize that Grid is the first CSS module created specifically to address the layout concerns we struggled with not long ago when building websites…

The Difference Between CSS Grid and Flexbox

As previously mentioned, Flexbox is intended for one-dimensional layout, and Grid is for two-dimensional layout. If you’re arranging a number of elements in one direction, meaning several elements in a single row or column, then you should use, or rather more appropriately, use Flexbox.

Flexbox offers much more flexibility in this scenario than CSS Grid. It requires less code and is easier to maintain.

Example of one-dimensional layout:

Element
Element
Element

In contrast, if you’re looking to create a structure in two dimensions, meaning both columns and rows, it’s recommended and probably more suitable to use CSS Grid to accomplish this.

Example of two-dimensional layout:

header
section
footer

In this case, CSS Grid offers much more flexibility, making the markup more compact and the code much simpler to maintain. Of course, you can combine both approaches and even desirable. In the last example, it would be appropriate to create a Grid for the layout or structure itself and use Flexbox to align content within the Header.

You can also combine both approaches and enjoy the best of both worlds. We’ll show examples of that in the course of the guide… So let’s start explaining the existing features of CSS Grid and how to use them.

Creating Your First Grid

The two main components of CSS Grid are the wrapper, which is essentially the parent element, and the elements within that wrapper, called child elements, also known as grid items.

So let’s reiterate just to make sure it’s clear – the wrapper is the Grid, and the elements are the content within that Grid. In any case, here’s the markup for a wrapper with six elements inside:

<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

To turn the wrapper into a Grid, simply apply the display: grid property:

.wrapper {
    display: grid;
}

The result will look like the following example:

1
2
3
4
5
6

However, as you can see, at this stage, it appears as if there are six elements stacked on top of each other. This is because we haven’t defined how we want the Grid to look, meaning we haven’t created that layout, those columns, and rows necessary for this kind of structure. Let’s see how to do that…

In the case of the examples in the guide (which are live Grid examples), I’ve added some CSS to make the Grid and its elements clearer and more comprehensible.


Creating Columns and Rows in Grid

In order to make the Grid we created become two-dimensional, we had to define columns and rows. Let’s create three columns and two rows. We will use the grid-template-rows property and the grid-template-columns property as demonstrated below:

.wrapper {
    display: grid;
    grid-template-columns: 33% 33% 33%;
    grid-template-rows: 60px 60px;
}

Since we wrote three values for grid-template-columns, we will get three columns. Similarly, since we wrote two values for grid-template-rows, we will get two rows.

The values themselves describe the width we want each column to be (33% in this case) and the height we want each row to be (60px).

It will look something like this:

1
2
3
4
5
6

To make sure you understood the connection between the values and the appearance of the Grid, take a look at the following example and try to grasp the relationship between the code and the structure of the Grid:

.wrapper {
    display: grid;
    grid-template-columns: 20% 60% 20%;
    grid-template-rows: 80px 40px;
}

The result will be in a similar style:

1
2
3
4
5
6

Additionally, it’s not necessary to use percentages; you can use absolute units, viewport units, and even the calc function, and similar techniques.

Moreover, you can use a new unit called Fractional Unit, which saves a lot of headaches. We will talk about this further and explain why it’s better than using percentages…


Positioning Elements in Grid

The next step will be to understand how to position elements in Grid. This is the most interesting part where you gain power. It’s very simple and allows you to create wonderful layouts quickly.

So, let’s give another example and create a Grid with three rows and three columns (3×3) using the following Markup:

<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

Let’s add the following CSS:

.wrapper {
    display: grid;
    grid-template-columns: 33% 33% 33%;
    grid-template-rows: 60px 60px 60px;
}

The result will be something like this, and I believe it’s clear to you why (if not, read the previous explanations again):

1
2
3
4
5
6

Note that we see a Grid with only two rows (3×2) even though we defined it to have three rows (3×3). The reason for this is that there are only six elements filling the Grid. If we had added three more elements to the Markup (or fewer), they would have filled the third row…

To change the position of an element and even change its size, we’ll target the same element and use the following properties: grid-column-start and grid-column-end.

For example, let’s use the following CSS:

.wrapper > div:nth-child(1) {
    grid-column-start: 1;
    grid-column-end: 4;
}

What we’re defining here is that the first element will start at the first Grid line and end at the fourth Grid line (in terms of columns). In other words, it will span across the entire row. This is how it will look on the screen:

1
2
3
4
5
6

I assume you might be a bit confused about talking about the fourth Grid line when we have only three columns. Take a look at the following image describing Grid Lines in white, and you’ll understand why…

The concept of Grid lines is relevant for both columns and rows, of course.

The Grid Lines

By the way, now (in one of the examples above), we’ve used all the rows of the Grid we created. When we defined that the first element spans across the entire row, it pushed all the other elements down.

Okay… so there are also the properties grid-row-start and grid-row-end, and using them is done in the same way. So, to make sure you’ve understood the concept behind Grid Lines properly, let’s play around a bit with the Grid elements we’ve created.

Take a look at the following CSS:

.wrapper > div:nth-child(1) {
    grid-column-start: 1;
    grid-column-end: 3;
}

.wrapper > div:nth-child(3) {
    grid-row-start: 2;
    grid-row-end: 4;
}

.wrapper > div:nth-child(4) {
    grid-column-start: 2;
    grid-column-end: 4;
}

Here’s the result of this code. Pause and think for a moment why the Grid looks like this. It’s really not that complicated…

1
2
3
4
5
6

Notice that there’s also a shorter way to achieve the same result using the span keyword, followed by the number of columns or rows it should span:

.wrapper > div:nth-child(1) {
    grid-column: 1 / span 2;
}

.wrapper > div:nth-child(3) {
    grid-row: 2 / span 2;
}

.wrapper > div:nth-child(4) {
    grid-column: 2 / span 2;
}

Moreover, we can achieve the same outcome using the span technique, where you specify the number of columns or rows that the element should stretch across:

.wrapper > div:nth-child(1) {
    grid-column: 1 / span 2;
}

.wrapper > div:nth-child(3) {
    grid-row: 2 / span 2;
}

.wrapper > div:nth-child(4) {
    grid-column: 2 / span 2;
}

CSS Grid has many more properties we haven’t touched on yet, and they are equally amazing. Let’s take a look at some of those properties…


The Grid-Area Property

The grid-area property can serve as a shorthand for the properties mentioned in the previous part. I’m talking about these properties:

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

Using grid-area is done like this:

grid-area: <row-start> / <column-start> / <row-end> / <column-end>

Let’s take a look at the following example, called Example A. We’ll create a new Grid for illustration purposes with 11 elements using the following Markup:

<div class="wrapper">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
</div>

Let’s define that element number 5 will have the following property:

.wrapper {
    display: grid;    
}
    .wrapper > div:nth-child(5) {
    grid-area: 1 / 2 / 5 / 7;
}

In a single CSS rule, we’ve defined that element number 5 will start at row 1 and column 2. Also, it will end at row 5 and column 7. The result will be like this:

1
2
3
4
5
6
7
8
9
10
11

Don’t forget – the start and end of rows and columns of that element refer to those same Grid lines we mentioned earlier.

Pretty cool, right? In any case, if you’re wondering how we achieved spacing between each element, the answer lies in the grid-gap property.


The Grid Gap Property

The grid-gap property sets the spacing between rows and columns in the Grid, and it’s essentially a shorthand for the following properties:

You can use it like this, and I won’t explain beyond this point because it’s self-explanatory. Just note that the first value is the gap between rows, and the second value is the gap between columns in the Grid.

.wrapper {
    display: grid;
    grid-gap: 4px 2px;
}

 

The Fr Unit – Fractional Unit

The Fr unit eliminates the need to use math and works based on the available space in the container. Let’s say we want to divide our Grid into three equal columns. We can easily do this using percentages – all we have to do is write grid-template-columns: 33% 33% 33%.

But what if we wanted to use the property grid-gap: 10px? Since we have two gaps (due to three columns), our Grid’s width will now be 100% + 20px, creating unwanted horizontal scrolling or elements overflowing their container.

Of course, we could use the calc function to solve the problem, but using the Fr unit is much simpler – grid-template-columns: 1fr 1fr 1fr. Let’s see some examples of using the Fr unit.

Here’s the markup we’ll use:

<div class="wrapper">
    <div>1Fr</div>
    <div>1Fr</div>
    <div>1Fr</div>
    <div>1Fr</div>
    <div>1Fr</div>
    <div>1Fr</div>
</div>

And here’s the CSS:

.wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
    grid-auto-rows: 80px; /* don't mind this property just yet */
}

The result will look like this:

1Fr
1Fr
1Fr
1Fr
1Fr
1Fr

The grid-auto-rows property is another CSS Grid property that sets the minimum height for all rows. Similarly, grid-auto-columns sets the minimum width for columns.

By the way, you can write this in a shorter way using the repeat function, which allows for more readable and compact code:

.wrapper {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 80px; 
}

You can also mix different unit types. For example, if we have two elements with a fixed width of 100px each and we want the third element to take up the remaining width, you can use the following CSS:

.wrapper {
    display: grid;
    grid-template-columns: 100px 100px 1fr;
    grid-auto-rows: 80px;
}

The result will be like this:

100px
100px
1Fr

It’s important to note that when using the Fr unit, you’re not limited to integer values – you can also use fractional values, like this:

.wrapper {
    display: grid;
    grid-template-columns: 1.5fr 3fr 4.5fr;
    grid-auto-rows: 80px;
}

And the result will be like this:

1.5fr
3fr
4.5fr

Here’s another short post I wrote that presents several examples of using the Fr unit in CSS Grid.


Aligning Elements in Grid

Elements in a Grid can be aligned with respect to the Grid container using the horizontal axis (columns) and the vertical axis (rows) by utilizing the Box Alignment Module of CSS.

align-content aligns the elements along the rows, and justify-content aligns the elements along the columns. Let’s see some examples – let’s assume we have a Grid with the following CSS:

justify-content: start

.wrapper {
    display: grid;
    width: 100%;
    height: 300px;
    grid-template-columns: repeat(4, 45px);
    grid-template-rows: repeat(4, 45px);
    grid-gap: 0.5em;
    border: 2px solid #424242;
    justify-content: start; 
}

The result will be like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

* Note the justify-content: start property; it’s the default property.

justify-content: end

.wrapper {
   justify-content: end;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

justify-content: center

.wrapper {
    justify-content: center;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

justify-content: space-around

.wrapper {
   justify-content: space-around;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

justify-content: space-between

.wrapper {
    justify-content: space-between;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

justify-content: space-evenly

.wrapper {
    justify-content: space-evenly;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

align-content: start

.wrapper {
    align-content: start;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

* Note the `align-content: start` property; it’s the default property.

align-content: end

.wrapper {
    align-content: end;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

align-content: center

.wrapper {
     align-content: center;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

align-content: space-around

.wrapper {
    align-content: space-around;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

align-content: space-between

.wrapper {
    align-content: space-between;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

align-content: space-evenly

.wrapper {
    align-content: space-evenly;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Creating a Website Layout using CSS Grid

I assume I’ve covered a lot, but before we conclude this part of the guide, I want to touch on another point related to the new property called grid-template-areas, which is related to the grid-area property we discussed earlier.

For the purpose of explanation, let’s create a basic website layout using CSS Grid. We’ll use the following markup:

<div class="wrapper">
    <header>header</header>
    <nav>nav</nav>
    <section>section</section>
    <aside>aside</aside>
    <footer>footer</footer>
</div>

Let’s add the following CSS:

.wrapper {
	display: grid;
	grid-template-areas:
    "header header header"
    "nav section aside"
    "footer footer footer";
	grid-template-rows: 80px 1fr 50px;
	grid-template-columns: 15% 1fr 15%;
	grid-gap: 4px;
    height: 360px;
}
    
header {
    grid-area: header;
}

nav {
    grid-area: nav;
}

section {
    grid-area: section;
}

aside {
    grid-area: aside;
}

footer {
    grid-area: footer;
}

Here’s the result:

header
section
footer

Please pause for a moment – are you catching the excitement? To start with, notice the minimal amount of code lines we had to write in order to create this structure.

It’s reasonable to assume that without CSS Grid, the code would have been at least five times longer. Beyond that, pay attention to the grid-template-areas property we used…

More information about grid-template-areas in another post I wrote, but for now, let’s stay here…

The Grid Template Areas Property

The grid-template-areas property defines areas within any Grid. You can assign names to elements using the grid-area property, and then refer to those names in the grid-template-areas property.

If we look at the last example we showed – you can see that there are three areas:

  • "header header header"
  • "nav section aside"
  • "footer footer footer"

Note that each area is defined within opening and closing quotation marks, and you can use a period to reference elements without a name.

You can understand that there are three columns in total, where the header spans across the entire first row.

The second-row area, on the other hand, is divided into three separate parts (according to their names), and the width of each is determined by the grid-template-columns property, as explained at the beginning of the guide. Also, the footer spans across the entire third row.

Assuming we want the navigation to span the entire height – the only change we need to make is in the CSS at the grid-template-areas property, like this example:

.wrapper {
	grid-template-areas:
    "nav header header"
    "nav section aside"
    "nav footer footer";
}

And the result, as you can imagine, will be this:

header
section
footer

 

What About Responsiveness?

If you play with the screen size, you’ll notice that our layout expands and contracts according to the width of the container, without needing any intervention.

But if, for the sake of argument, we want to change the layout for mobile, we can simply add the following media query, where the only change we make will be at the grid-template-areas property:

@media (max-width: 768px) {
    .wrapper {
    grid-template-areas:
    "header header header"
    "nav nav nav" 
    "section section section"
    "aside aside aside"
    "footer footer footer";
    grid-template-rows: 50px 30px 1fr 60px 30px;
    }
}

The result when the screen width is less than 768px will look like this:

header
section
footer

The fact that the only thing we needed to change to achieve this was a single CSS property is nothing less than wonderful…

By the way, in many cases, we can create responsive layouts without using any Media Queries at all, and that’s also achievable through CSS Grid.

Take a look at the guide I wrote about the CSS Grid minmax function.

A Few Words About Browser Support

Today, you can use CSS Grid in all modern browsers, and about 85% of all users worldwide use browsers that support CSS Grid.

In any case – when there’s doubt about the support of a specific feature, I always recommend visiting caniuse.com to check the browser support for that functionality.

If you visit the link, you’ll see at the top-right corner of the screen the global percentage of users who use supported browsers.

You can see that there’s very broad support for the CSS Grid feature among the majority of modern browsers, and that’s excellent news.

You can also see that there’s only partial support in IE11, but I hope you’re not concerned about that – personally, I’m certainly not.

To Sum Up

Of course, there are many more options we haven’t touched upon in the context of CSS Grid, and this was just scratching the surface. I can say that the more I delve into the topic, the more I’m amazed by the possibilities and the number of properties that exist for CSS Grid.

Here’s a post, by the way, in the same context, demonstrating the power of CSS Grid and showing how to create responsive layouts without using Media Queries and using the minmax function. Take a look when you have the chance…

Have you built websites or user interfaces using CSS Grid? If not, now is the time to start – the sooner we embrace this module, the easier our lives will become.

So, I hope this guide will help you start using CSS Grid, and I promise to update it and add features and examples we haven’t talked about yet.

If you liked the post, you’ll probably also like the post about CSS Variables, definitely something you’ll want to learn as well. So, as always, if you have comments, questions, or ideas about what was discussed, I’d be happy if you share them in the comments… 🙂

Roee Yossef
Roee Yossef

I develop websites & custom WordPress themes by design. I love typography, colors & everything between, and aim to provide high performance, seo optimized websites with a clean & semantic code.

0Comments...

Leave a Comment

 

Up!
Blog