A Complete Guide to Grid

Last updated on:
This article is in-progress. We're trying to stay on-top of grid layout and make sure we have some information about it. But know that grid is extremely new, not well supported, and in-flux in browserland still.

The grid property in CSS is the foundation of Grid Layout. It aims at fixing issues with older layout techniques like float and inline-block, which both have issues and weren't really designed for page layout.

You start by establishing a grid context on an element:

.area {
  display: -ms-grid; /* prefix for IE 10 */
  display: grid; /* or inline-grid */

Then you define what that grid layout will be like. Think columns and rows like a spreadsheet (or table). Then, you can define for each child a column and a row (resulting in a cell). No markup changing is involved; everything is done through CSS.

Along with the fact this method fixes the issues we encounter with older layout techniques, its main benefit is you can display a page in a way which can differ from the flow order.


Since CSS Grid Layout is a whole module and not a single property, it gathers a bunch of properties meant to be used together. Some are meant to be set on the parent (grid) element, others on the children.

The `fr` Unit

The fr unit can be used for grid-rows and grid-columns values. It stands for "fraction of available space". Think of it as percentages for available space when you've taken off fixed-sized and content-based columns/rows. As the spec says:

The distribution of fractional space occurs after all 'length' or content-based row and column sizes have reached their maximum.

Coming Soon

The properties listed so far are the very basics to use the grid layout; they are also the first (and currently only) properties to be supported in this module.

According to the official specifications, there are a lot more involved including:

  • grid-template: allows grid definition through a template of identifiers
  • grid-column-position: current grid-column since grid-column is supposed to be a shorthand for grid-column-position and grid-column-span
  • grid-row-position: same as above
  • grid-position: shorthand for grid-column-position and grid-row-position
  • grid-span: shorthand for grid-column-span and grid-row-span
  • grid-area: shorthand for grid-column-position, grid-row-position, grid-column-span and grid-row-span
  • grid-auto-columns: change default size for columns
  • grid-auto-rows: change default size for rows
  • grid-auto-flow: allows grid-items to automatically flow in available cells

Unfortunately, these properties are currently unsupported. We'll update this article over time to document and include examples.


Consider a structure like the following:

<div class="main">My awesome content here</div>
<footer class="footer">Some informations here</footer>
<header class="header">My site title goes here</header>
<aside class="sidebar">Here is my side content</aside>

Note how the markup order has absolutely no impact on the final rendering.

body {
 /* First, we define body as a grid element */
 display: grid;
 /* Then, we define the number of columns we want by setting their dimensions */
 /* Beware, gaps between columns will be actual columns too */
 /* 1. This means there are 3 columns: 
  * the first one is 200px wide
  * the second one will be a margin (1%) 
  * the third one will occupy the remaining space 
 grid-columns: 200px 1% 1fr; /* 1 */
 /* Now we define the number of rows and their dimensions */
 /* 2. this means there are 5 rows: 
  * the first one will be sized according to its content
  * the second one will be a margin
  * the third one will be sized according to its content
  * the fourth one will be a margin as well
  * the last one will be sized according to its content 
 grid-rows: auto 15px auto 15px auto; /* 2 */
 /* The body element is now a 3*5 grid. */
/* Both the header and the footer will be full width, so we have to make them occupy the 3 columns */
.footer {
  grid-column-span: 3;

/* Let's define in which row the header will be: the first one */
.header {
  grid-row: 1;
/* Same for the footer: the last one so the fifth (remember margins count as cols/rows */
.footer {
  grid-row: 5;
.sidebar {
  /* The sidebar will occupy the first column which is 200px wide */
  grid-column: 1;
  /* And the 3rd row (there are the header and a margin before) */
  grid-row: 3;
.main {
  /* The main content will be on the 3rd column and the 3rd row */
 grid-column: 3;
 grid-row: 3;

With a few other lines of CSS to handle styling issues, we have a decent layout with absolutely no floats, no inline-blocks, no defined widths, no defined heights and no margins and completely independant of the flow order. Pretty neat, right?

Check out this Pen!
If you see the 4 parts one under the other, your browser doesn't support CSS Grids. Please switch to a supported browser to enjoy the demo.

Now let's add a 2nd sidebar to, for instance, display ads. It will be on the right side of the main content. There are a few tweaks to do in order to make everything works.

/* We first change the grid-columns definition on the grid element to add 2 new columns: one margin and one sidebar */
body {
  display: grid;
  grid-columns: 200px 1% 1fr 1% 100px;
  grid-rows: auto 15px auto 15px auto;
  /* We could have writen grid-rows: auto (15px auto)[2] */

/* Both the header and the footer will expand to 5 columns instead of 3 */
.header, .footer {
  grid-column-span: 5;

.ads {
  grid-column: 5;
  grid-row: 3;

Done! We now have a layout with full-width header and footer, 3-columns on the main part including 2 fixed-width columns with about 13 lines of CSS.

Check out this Pen!
If you see the 5 parts one under the other, your browser doesn't support CSS Grids. Please switch to a supported browser to enjoy the demo.

What about responsive design? Easy as a pie. Let's slightly tweak our design when under 600px device width.

@media all and (max-width: 600px) {
  body {
    /* First, we make the body 1-column and 5 rows spaced by 4 margin rows */
    grid-columns: 1fr;
    grid-rows: auto (1% auto)[4];
    /* This is the same as:
     * grid-rows: auto 1% auto 1% auto 1% auto 1% auto;
  /* Then we say to all elements they belong in the only existing column */
  .header, .ads, .sidebar, .main, .footer {
    grid-column: 1;
  /* Now we define their row; don't forget spacing rows! */
  .header  { grid-row: 1; }
  .ads     { grid-row: 3; }
  .main    { grid-row: 5; }
  .sidebar { grid-row: 7; }
  .footer  { grid-row: 9; }
  /* We even can create grids inside grids */
  .ads {
    display: grid;
    grid-columns: 1% (32% 1%)[3]; /* 1% 32% 1% 32% 1% 32% 1% */
    grid-rows: 2; /* One for the title, one for the images */
  .ads h2  { grid-row: 1; grid-column-span: 3; }
  .ads img { grid-row: 2; }
  .ads img:nth-of-type(1) { grid-column: 2; }
  .ads img:nth-of-type(2) { grid-column: 4; }
  .ads img:nth-of-type(3) { grid-column: 6; }

Have a look at this Pen and resize your browser to see the magic!

Here is a grid system made with CSS Grid Layout and Sass:

Check out this Pen!
If you see all items one under the other, your browser doesn't support CSS Grids. Please switch to a supported browser to enjoy the demo.

If you feel uncomfortable with the idea of having columns and rows as margins, I guess you can still use actual margins on element but that defeats the purpose a bit. Or you could use a CSS preprocessor to ease you the calculations; here is a demo.


Other Resources

Browser Support

Chrome Safari Firefox Opera IE Android iOS
none none none none 10+ none none

Support coming in WebKit/Blink and Gecko (currently in some nightly builds).


  1. Seth
    Permalink to comment#

    Awesome article! thanks for the early peek at the grid spec.

    Maybe it was just how you did your examples but one thing I didnt like was how the margin was also a row/column. I felt it took away from the clarity of the grid semantics, as you have to remember to put something in row 3 rather than 2 because 2 is supposed to be a margin. It feels just as weird as the ole spacer divs from way back in the day.

    Is there any properties like grid-spacing or grid-row-margin/grid-column-margin? These would feel much more natural.

    say we have 4 rows in our grid layout (same concept would apply for columns)

    /* shorthand would define top/bottom margin for each row*/
    /*would define top/bottom margin for each row*/
    grid-row-margin:15px 10px 30px 20px;
    /*would define different top/bottom margin for each row (top bottom, top bottom, ect...)*/
    grid-row-margin:0px 15px, 5px 10px ,0 30px, 0 20px;
    /* would define top margins only*/
    grid-row-margin-top:0px 5px 0px 0px;
    /* would define bottom margins only*/
    grid-row-margin-bottom:15px 10px 30px 20px;


    • Manuel Rego
      Permalink to comment#

      Currently you can only do it like in the article adding the gutters directly as any other row/column.

      However it’s planned to add some properties (column-gap and row-gap) to manage this. Similar to what we already have in multi-column with column-gap.

  2. Abby Larsen
    Permalink to comment#

    Thanks for enlightening me on “fr.” I’m currently reading Rachel Andrew’s book, CSS3 Layout Modules (2.0), and was puzzled by what “fr” could possibly stand for. I’m bookmarking this article as a refresher once I finish the book!

  3. delebash
    Permalink to comment#

    As always nice article! For more on CSS-Grid Layout Module, check out Rachel Andrew her site has some more up to date examples. It demo’s grid-area, span, grid-templates

    • raamamoorthy
      Permalink to comment#

      This is an exact grid system, if we implement, it can easily solve the layout issues and will be neat on all devices.

  4. Millennium Outlaw
    Permalink to comment#

    Any ETA on when exactly the grid layout will be accepted by Gecko/WebKit browsers?

  5. Senpai
    Permalink to comment#

    Why the hell isn’t this widely supported yet?

  6. Daniel Elebash
    Permalink to comment#

    yeah, I feel ya, if you look at bugzilla you can see that Mozilla is actively working on it. Sadly no eta from what I can find. Hope IE and Safari get on board, its a nice feature and will cut down on the size of any framework sugar you may use or not use one at all.

    • lunar
      Permalink to comment#

      Funny thing about that… IE 10+ is currently the only browser that supports grid layout, so we can thankfully check them off of our list. :D As I understand it, Microsoft was the major player behind this standard. Basically, they took their WPF grid layout and ported it to the web, which is why they are so far ahead. They already had the code. Anyway, I think mainline chrome supports it behind the experimental flag. Really, I think we’re waiting on Safari and Mozilla at this point. CSS grid will be a wonderful thing when we can finally use it.

  7. Ajedi32
    Permalink to comment#

    Could you please update this article to include the unprefixed versions of these properties in the demo code? Chrome actually does support CSS Grid Layout, you just need to enable the “Experimental Web Platform Features” flag first.

    • Al Street
      Permalink to comment#

      Here’s a pen of part of this article with the prefixes removed:

  8. Al Street
    Permalink to comment#

    oops. Trying again:

  9. Paulo Sergio

    this article helped me a lot…
    I’m enchanted on how we can easily draw layout sample using grid.

  10. Vitor Melo
    Permalink to comment#

    Isso vai ficar pronto quando 2xxx? Desculpe mas eu embora fico curioso, não tentarei aprender até então. O tutorial está de parabéns.

  11. Thillai
    Permalink to comment#

    Is Grid layout system developed by microsoft, as we are seeing its support on IE10+ browsers

  12. Juan Carlos
    Permalink to comment#

    Every browser supports this grid property?

    • Dave Mackey
      Permalink to comment#

      No, see the “Browser Support” section – no browser supports this except IE10 (and I’m guessing Edge?)

  13. Benjamin Milde
    Permalink to comment#

    Would be nice if the examples could be updated with unprefixed properties, which now do work in chrome behind a flag.

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

There's a whole bunch of content on CSS-Tricks.

Search for Stuff   •   Browse the Archives

Get the Newsletter ... or get the RSS feed