Kermode

/ˈkɜːrmoʊd/
The Spirit Bear

Written by Gray Gilmore

I make websites for a living. I love CSS and building simple and modular stylesheets. Somewhere along the way I also turned into a Ruby developer. Life comes at you fast I guess. You can read my resume to learn about my journey so far.

You can find me as @graygilmore on several platforms:

Good ol' fashion email works, too: hello@kermode.co

You can subscribe to this blog via RSS: XML, JSON

A Simple Primer for CSS Grid Layout

Grids on the web have a storied history. I remember a Webmonkey (RIP) article that explained how to set up a simple grid using framesets. Times were simpler then. Developers started abusing tables. Then we just started floating everything this way and that. We got tired of needing to self-clear child elements so we started inline-blocking everything. We declared flexbox to be the saviour of everything but we’ve never really been able to stop hacking our way through it.

CSS Grid Layout aims to solve a number of the problems that developers run into when creating lots of different types of web applications. We’re going to look at a simple case today to show off the easy side of CSS Grid Layout.

Our Grid

We’re going to be working with a simple grid of products. Having worked within the ecommerce space for a number of years I see this particular layout come up very often. We’re going to focus on a category listing of products. On large screens we’ll display three products per row and we’ll move that number down as the viewport gets smaller.

If we were doing this with inline-block our Sass would look something like this (view demo):

.products-grid {
  font-size: 0; // inline-block hack

  @media screen and (min-width: 600px) {
    margin: 0 -0.5rem; // hack to stretch our products to fill the container
  }
}

.products-grid-item {
  font-size: 1rem; // reset inline-block hack
  text-align: center;

  @media screen and (min-width: 450px) {
    display: inline-block;
    width: calc(50% - 1rem);
    margin-top: 2rem;
    padding: 0 0.5rem;
  }

  @media screen and (min-width: 900px) {
    width: calc(33.33% - 1rem);
  }

  @media screen and (min-width: 1200px) {
    width: calc(25% - 1rem);
  }

  img {
    display: block;
    width: 100%;
  }
}

It’s not the worst bit of code that we could write but it’s littered with comments that actually use the word “hack” in it. We’re using a feature for CSS in a way that it wasn’t really designed for. This is where CSS Grid Layout comes into play.

Our Grid: The Redux

CSS Grid Layout is very powerful and is capable of creating incredibly complex layouts. We only need a few basic tools in order for us to convert our inline-block layout, though.

  1. display: grid – this is the new display value that will enable us to use all that CSS Grid Layout has to offer.
  2. grid-template-columns: <values> – this will allow us to define how many columns we would like our grid to display our products in.
  3. grid-gap: <values> – this is the shorthand for setting grid-column-gap and grid-row-gap and will let us define the space between our products.

Those are the only three features that we need in order to get started with CSS Grid Layout! Our Sass now looks like (view demo):

.products-grid {
  display: grid;
  grid-template-columns: 1fr;
  grid-gap: 1rem;

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

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

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

.products-grid-item {
  text-align: center;

  img {
    display: block;
    width: 100%;
  }
}

While we haven’t dramatically reduced the number of lines required to create our layout, we’ve reduced the complexity and we’ve made our code significantly more explicit about what it’s trying to accomplish. Let’s go through these new additions one by one.

display: grid

This is necessary for the rest of the styles to function. On its own display: grid; will make no changes to how the content is displayed. You can think of it like a flag you can turn off/on to enable the rest of the element’s styles (just like flexbox).

grid-template-columns

This is one of the most confusing parts of CSS Grid Layout because it introduces a new value which I’ve used above: fr. W3 defines the unit like this:

A flexible length or is a dimension with the fr unit, which represents a fraction of the free space in the grid container.

This works a lot like flex-grow: 1 when using flexbox. In our case, 1fr means “one unit of space of the total number of units”. So if we had our column values as 1fr 2fr 3fr our first column would take up 1/6 of the remaining space (space after all grid-gap values are taken into account).

grid-gap

Here we’re setting our gutters to be 1rem both to the left/right and above/below our products. What makes this so much better than using padding or margin is that this gutter will only appear between our products. This means we don’t need any special rules to remove the gutter where it isn’t needed (like the above the top row or below the bottom row).

Browser Support

I’ve got some good news and some bad news.

The good:

The bad:

2017 will be the year of CSS Grid Layout!

What’s Next?

This is just a tip of the iceberg of what CSS Grid Layout can provide. While the example above doesn’t utilize all of the features available to us it should give you a taste of what’s possible. Feel free to fork the examples and see what other creations you can create.

More Reading