Getting Started with CSS Grid

Avatar of Robin Rendle
Robin Rendle on (Updated on )

Why is CSS Grid a big deal and why should we care?

Well, CSS Grid is the first real layout system for the web. It’s designed for organizing content both into columns and rows and it finally gives developers almost God-like control of the screens before us. That means that we can finally ditch decades of hacks and workarounds for setting elements on a web page – ultimately it means that complex layouts and beautifully typeset pages are now not only possible but easy and maintainable.

With CSS Grid, the web is about to become a much more beautiful place than what we’re accustomed to.

OK, but how does Grid work? There are a lot of complex tutorials out there that go into an awful lot of detail but I think we should start with the very basics. What we’ll be making here is a relatively simple type specimen, with a bunch of characters from an alphabet laid out on a page.

To get started we’ll add our markup:

<div class='wrapper'>
  <div class='letter'>
    A
  </div>
  <div class='letter'>
    B
  </div>
</div>

First up we’ll style those letters to use the right font-size and color and then we’ll center those letters in the divs with flexbox properties like align-items and justify-content. And yes, that’s right! CSS Grid doesn’t replace flexbox properties as much as it compliments what they already do. We can even use many of these properties in conjunction with CSS Grid. But for now let’s return to the demo:

In the example above we have two simple divs sitting on top of one another because they’re default is display: block. Next up we’ll set our parent element to use Grid layout:

.wrapper {
  display: grid;
}

Which will then lead to this:

See the Pen Type Specimen Grid Demo – 1 by Robin Rendle (@robinrendle) on CodePen.

Now you might see that nothing really happened. And you’d be right! Unlike setting display: inline-block; or display: inline;, it’s not entirely clear what happens when we set display to grid. In fact, to get our grid to actually do something we first need to feed it a certain number of columns or rows. In this example we’ll just align the letters next to each other into two columns:

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-column-gap: 1px;
  background-color: black;
}

Let’s break these new lines of code down. First we create two columns of our grid with grid-template-columns. That 1fr value might seem super weird if you’ve never seen it before but it’s a valid CSS unit that tells each column to be one fraction of our grid. In this instance, that means there will be two columns of equal width.

This will end up looking something like this:

See the Pen Type Specimen Grid Demo – 2 by Robin Rendle (@robinrendle) on CodePen.

Hooray! It works. But see that curious gap between the two columns? That’s the background of the wrapper peaking through each letter div and that’s because we’ve set the grid-column-gap property to 1px. Usually, we’d want to give a larger column-gap then that, especially if we’re aligning text blocks next to each other. But in this instance, a single pixel is good enough for us.

So what happens if we add two new letters to our markup? How will that change the layout?

<div class='wrapper'>
  <div class='letter'>
    A
  </div>
  <div class='letter'>
    B
  </div>
  <div class='letter'>
    C
  </div>
  <div class='letter'>
    D
  </div>
</div>

Well, technically it won’t change the grid at all – we’ve already told the grid to have two columns so those two letter divs are going to sit in place directly beneath the others and be exactly 1fr wide:

See the Pen Type Specimen Grid Demo – 3 by Robin Rendle (@robinrendle) on CodePen.

Now here’s the weird thing – why isn’t there a 1px gap between letters A and C as well as between B and D? Well, grid-column-gap is only for columns and what we’ve effectively done here is create a new row in our grid. We’ll have to use grid-row-gap to see that change take effect:

.wrapper {
  grid-column-gap: 1px;
  grid-row-gap: 1px;
  /* other styles go here */
  /* we could have also used the shorthand `grid-gap` */
}

And here’s what that looks like:

See the Pen Type Specimen Grid Demo – 4 by Robin Rendle (@robinrendle) on CodePen.

We’ve created our very first grid. We’ve made a row and a column and all we’ve really had to do is change the markup. But let’s just explore our columns a little more. What would happen if we add another value to the grid-template-columns property? Like this:

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

Well, we’d create another column of course! And notice how we can clearly see the background of the wrapper element now because there aren’t any children to fill that space:

See the Pen Type Specimen Grid Demo – 5 by Robin Rendle (@robinrendle) on CodePen.

And if we change the value of a fr in that property then that would effectively create what’s known as an asymmetric grid. Let’s say that we wanted our first column in our grid to take up three times the amount of space as the other two columns:

.wrapper {
 grid-template-columns: 3fr 1fr 1fr;
}

That would lead to the columns with A and D to be larger than the other two columns, just as we’d expect:

See the Pen Type Specimen Grid Demo – 6 by Robin Rendle (@robinrendle) on CodePen.

Isn’t that powerful? No longer do we have to worry about negative margins or the perfect % value of a grid column to align things properly. We can make super complex grids without having to do any of the math that we would’ve been forced to do in the past. Now we just need to add a new value to the grid-template-columns property and voilá, a new grid column appears like magic!

But what about responsive grids, you might ask? Well that’s really just as simple as changing that property within a media query. Let’s say that we want 2 columns as our default grid size then at 500px we want 3 columns and finally, on larger screens, we’ll shift all that content into 4 columns. All we’d need to write is this:

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

@media screen and (min-width: 500px) {
  .wrapper {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

@media screen and (min-width: 800px) {
  .wrapper {
    grid-template-columns: 1fr 1fr 1fr 1fr;
  }
}

Make sure to open up this demo in a new tab and change the size of the viewport to see the responsive magic happen!

So the grid-template-columns property is a lot more complicated than what I’ve shown here but this is a great starting point. Next up we ought to learn about the real, life-changing property in the CSS Grid spec: grid-template-rows.

Ok, let’s go into it blind. In the small bit of code below, and with what we’ve learned so far about Grid, let’s figure out what this new property might do:

.wrapper {
  display: grid;
  grid-template-columns: 3fr 1fr 1fr;
  grid-template-rows: 1fr 3fr;
}

Instead of setting the width of columns and their relationship with one another, we’re now going to set the height of rows and their relationship. So if we have two rows like in our previous demo and the last unit is set to 3fr then that means the second row will always be three times the height of the first:

See the Pen Type Specimen Grid Demo – 8 by Robin Rendle (@robinrendle) on CodePen.

This might look pretty simple yet previously we’ve never really been able to do this. We’ve always had to write gross hacks like setting a min-height on a specific element or changing a class name. But we’ve never been able to create relationships between rows like this before; that’s what makes CSS Grid so powerful.

With this tiny bit of knowledge and a handful of new properties, we can create fabulously complex layouts – asymmetric and responsive grids being just one small part of them. And so far this has only been a glimpse into the monstrous CSS Grid spec, as there’s an awful lot to cover. But I think that Jen Simmons described it best when she wrote about Grid:

We need to explore CSS Grid until we understand what it wants to do, what it can be forced into doing, and what it refuses to do. Many designers may not ever learn to code CSS, but you need to understand CSS well enough to understand our artistic medium.

And sure, all the code above looks very strange at first. But what it means is that we don’t have to use giant CSS frameworks and also a whole bunch of layout hacks are now completely irrelevant. But what really excites me most about Grid is that it compels us to see the space inside a browser in a completely new way.

We’ll have to not only learn a bunch of new properties, but we’ll also have to entirely rethink what we’ve learned in the past. So CSS Grid is not just a spec but a strange philosophy unto itself.

Let’s figure it out together!

Browser Support

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
575211*1610.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
12312412310.3

More Information