Enough Grid to be Dangerous

CSS Grid is an awesome new tool for layouts that makes life super easy. Here's a quick rundown.

This is by no means an exhaustive guide to CSS grid. Our goal is just to give you a nice start with some basic building blocks. I’m going to give you a quick overview of the most-likely use cases here, but if you want to drown in details, check out the amazing Grid by Example and this excellent CSS Tricks guide.

Basic Concepts

Grids are divided into rows and columns, which you define in CSS. You assign these rows and columns with the grid-template-rows and grid-template-columns properties, followed by space-separated values that determine the size of each row/column.

For example, grid-template-columns: 50px 50px 50px; will create a grid with three 50px columns. And grid-template-rows: 150px 30%; will create two rows, one at 150px, and one at 30% of the parent’s height.

Trick Properties

You can use any CSS units in these declarations, but there are a few special ones you should be aware of:

fr

This unit is a measure of free space remaining in the grid. grid-template-columns: 1fr; would create a single column at 100%, grid-template-columns: 1fr 1fr; would create two 50% columns, and grid-template-columns: 1fr 1fr 2fr; would create two 25% columns and one 50% column. For an example of how useful this is, imagine you’re creating a full-screen web app with the following layout:

<body id="grid">  
  <header>
  </header>
  <main>
  </main>
  <footer>
  </footer>
</body>  

You know how tall the header and footer are (100px for this example), but how do you set the height of the main element? Previously, you’d either use flexbox and prayer, or do something like height: calc(100% - 20px);. Now all you would have to do is create a grid on your body element:

See the Pen Grid Demo 1 by Adrian Bettridge-Wiese (@arbw) on CodePen.

[N.B. We're styling the appearance of the grid in another pen to keep things easy to read.]

But that requires that you know the height of the header and footer, and maybe you won’t. That’s where the next two properties come in!

min-content and max-content

These two properties are actually available anywhere you set width, but are very useful in grid. min-content sets the width of an element to the width of the largest element that can't be broken, and max-content to the "preferred" (almost always, "longest") width. So, if you're not sure what size your header and footer are (for example, if it changes based on viewport), you might do the following:

#grid {
  display: grid;
  grid-template-rows: max-content 1fr max-content;
}

minmax

minmax is a tool for controlling your fluid sized elements. It defines the minimum size of an element, and then how large you're willing to let it become. For example, let's look at the following layout:

<main id="grid">  
  <section id="col1"></section>
  <section id="col2"></section>
  <section id="col3"></section>
</main>  

Let's say we want the center column to be at least 500px, and expand until its twice the side of the side columns. Here's what we'd do:

See the Pen Grid Demo 2 by Adrian Bettridge-Wiese (@arbw) on CodePen.

Layout Helpers

There are a number of properties that will help you lay out your grid container.

grid-gap

grid-gap is a shorthand for grip-row-gap and grid-column-gap. It sets the gutters within the grid (not outside it—you'll need padding for that).

repeat

repeat is awesome. It saves you a lot of work if you're setting up, well...repeating grids. Here's an example:

<main id="grid">  
  <section id="col1"></section>
  <section id="col2"></section>
  <section id="col3"></section>
  <section id="col4"></section>
  <section id="col5"></section>
  <section id="col6"></section>
  <section id="col7"></section>
  <section id="col8"></section>
  <section id="col9"></section>
</main>  

If you wanted this grid to be two outer columns of 50px, filled with alternating 1fr and 2fr columns, you could do this:

#grid {
  grid-template-columns: 50px 1fr 2fr 1fr 2fr 1fr 2fr 1fr 50px; 
}

Or you could do this:

See the Pen Grid Demo 3 by Adrian Bettridge-Wiese (@arbw) on CodePen.

But where repeat really comes into its own is with auto-fill.

auto-fill

An auto-fill declaration tells the container to create as many columns of a certain size as it can given its size. This is what you need if you're making something like a grid of squares:

<main id="grid">  
  <article class="square"></article>
  <article class="square"></article>
  <article class="square"></article>
  <article class="square"></article>
  <article class="square"></article>
  <article class="square"></article>
  <article class="square"></article>
</main>  

If each square is 50px by 50px and we want to fit as many as we can into columns, we'd do this:

See the Pen Grid Demo 4 by Adrian Bettridge-Wiese (@arbw) on CodePen.

span (and grid-row/column-end)

You can do an awful lot of explicit positioning in your grid with the grid-row-start, grid-row-end, grid-column-start, and grid-column-end properties, but we really don't think you'll need it very often. That said, the -end properties are super useful because they let you make grid elements that fill multiple cells. One nice example would be a layout that looks like this:

<main id="grid">  
  <header></header>
  <section class="column"></section>
  <section class="column"></section>
  <footer></footer>
</main>  

If we want to make the header and footer both full width, but the columns each 50%, what do we do? One option is to put the two section elements in a container and make that its own grid, but here's another using span.

See the Pen Grid Demo 5 (Span) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Compatibility

Can I Use css-grid? Data on support for the css-grid feature across the major browsers from caniuse.com.

Grid currently works well on Chrome, Safari, and Firefox. IE and Edge have an outdated implementation of the spec that's frankly way more trouble than it's worth to use. If you do all your prefixing by hand, you'll be fine if you just don't write any vendor prefixes. However, you probably use an autoprefixer, which will helpfully prefix your grid code just enough to break the layout on IE and Edge. To avoid that, we use the following @supports rule:

@supports ((display: grid) and (not (display: -ms-grid))) {
}

The not part is there because autoprefixer will also oh-so-helpfully expand @supports (display: grid) into @supports ((display: grid) or (display: -ms-grid)).

Fallbacks

Most of the time, you can create an almost-as-good layout with flexbox. It won't let you control both axes as well as grid does, but it's passable. One exception is the square grid example from above, where I'd recommend using float instead.

The trick is to write your fallback first, and then follow it with the grid declaration (inside the @supports rule above). One cool thing is that display: grid will overwrite any floats you have in place, so you can include both declarations in one place. You may find that you have to

Here are fallback implementations of all the examples from above (without grid included, so you can see how they look):

Three-row fullscreen app

See the Pen Fallback Demo 1 (Fullscreen App) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Three columns, expanding center

See the Pen Fallback Demo 2 (Expanding Center Column) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Complicated repeating columns

See the Pen Fallback Demo 3 (Repeating Columns) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Square Grid

See the Pen Fallback Demo 4 (Square Grid) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Header, Two Columns, Footer

See the Pen Fallback Demo 5 (Header, Two Columns, Footer) by Adrian Bettridge-Wiese (@arbw) on CodePen.

Three-row App with Fallback in Place

Finally, here's an example of including the fallback with the grid code.

See the Pen Combined Fallback Demo (Fullscreen App) by Adrian Bettridge-Wiese (@arbw) on CodePen.