A Complete Guide to Grid

CSS Grid Layout is the most powerful layout system available in CSS. It is a 2-dimensional system, meaning it can handle both columns and rows, unlike flexbox which is largely a 1-dimensional system. You work with Grid Layout by applying CSS rules both to a parent element (which becomes the Grid Container) and to that elements children (which become Grid Items).

This article was ported over from Chris House's guide, by Chris himself, who is keeping both up-to-date.

Introduction

CSS Grid Layout (aka "Grid"), is a two-dimensional grid-based layout system that aims to do nothing less than completely change the way we design grid-based user interfaces. CSS has always been used to lay out our web pages, but it's never done a very good job of it. First we used tables, then floats, positioning and inline-block, but all of these methods were essentially hacks and left out a lot of important functionality (vertical centering, for instance). Flexbox helped out, but it's intended for simpler one-dimensional layouts, not complex two-dimensional ones (Flexbox and Grid actually work very well together). Grid is the very first CSS module created specifically to solve the layout problems we've all been hacking our way around for as long as we've been making websites.

There are two primary things that inspired me to create this guide. The first is Rachel Andrew's awesome book Get Ready for CSS Grid Layout. It's a thorough, clear introduction to Grid and is the basis of this entire article. I highly encourage you to buy it and read it. My other big inspiration is Chris Coyier's A Complete Guide to Flexbox, which has been my go-to resource for everything flexbox. It's helped a ton of people, evident by the fact that it's the top result when you Google "flexbox." You'll notice many similarities between his post and mine, because why not steal from the best?

My intention with this guide is to present the Grid concepts as they exist in the very latest version of the specification. So I won't be covering the out of date IE syntax, and I'll do my best to update this guide regularly as the spec matures.

Basics and Browser Support

To get started you have to define a container element as a grid with display: grid, set the column and row sizes with grid-template-columns and grid-template-rows, and then place its child elements into the grid with grid-column and grid-row. Similarly to flexbox, the source order of the grid items doesn't matter. Your CSS can place them in any order, which makes it super easy to rearrange your grid with media queries. Imagine defining the layout of your entire page, and then completely rearranging it to accommodate a different screen width all with only a couple lines of CSS. Grid is one of the most powerful CSS modules ever introduced.

As of March 2017, many browsers shipped native, unprefixed support for CSS Grid: Chrome (including on Android), Firefox, Safari (including on iOS), and Opera. Internet Explorer 10 and 11 on the other hand support it, but it's an old implementation with an outdated syntax. Edge support has been announced, but it's not here yet.

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

ChromeOperaFirefoxIEEdgeSafari
57445211*1610.1

Mobile / Tablet

iOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox
10.3NoNo565955

Aside from Microsoft, browser manufacturers appear to be holding off on letting Grid loose in the wild until the spec is fully cooked. This is a good thing, as it means we won't have to worry about learning multiple syntaxes.

It's only a matter of time before you can use Grid in production. But the time to learn it is now.

Important Terminology

Before diving into the concepts of Grid it's important to understand the terminology. Since the terms involved here are all kinda conceptually similar, it's easy to confuse them with one another if you don't first memorize their meanings defined by the Grid specification. But don't worry, there aren't many of them.

Grid Container

The element on which display: grid is applied. It's the direct parent of all the grid items. In this example container is the grid container.

<div class="container">
  <div class="item item-1"></div>
  <div class="item item-2"></div>
  <div class="item item-3"></div>
</div>

Grid Item

The children (e.g. direct descendants) of the grid container. Here the item elements are grid items, but sub-item isn't.

<div class="container">
  <div class="item"></div> 
  <div class="item">
  	<p class="sub-item"></p>
  </div>
  <div class="item"></div>
</div>

Grid Line

The dividing lines that make up the structure of the grid. They can be either vertical ("column grid lines") or horizontal ("row grid lines") and reside on either side of a row or column. Here the yellow line is an example of a column grid line.

Grid line

Grid Track

The space between two adjacent grid lines. You can think of them like the columns or rows of the grid. Here's the grid track between the second and third row grid lines.

Grid track

Grid Cell

The space between two adjacent row and two adjacent column grid lines. It's a single "unit" of the grid. Here's the grid cell between row grid lines 1 and 2, and column grid lines 2 and 3.

Grid cell

Grid Area

The total space surrounded by four grid lines. A grid area may be comprised of any number of grid cells. Here's the grid area between row grid lines 1 and 3, and column grid lines 1 and 3.

Grid area

Grid Properties Table of Contents

Properties for the Parent
(Grid Container)

display

Defines the element as a grid container and establishes a new grid formatting context for its contents.

Values:

  • grid - generates a block-level grid
  • inline-grid - generates an inline-level grid
  • subgrid - if your grid container is itself a grid item (i.e. nested grids), you can use this property to indicate that you want the sizes of its rows/columns to be taken from its parent rather than specifying its own.
.container {
  display: grid | inline-grid | subgrid;
}

Note: column, float, clear, and vertical-align have no effect on a grid container.

grid-template-columns
grid-template-rows

Defines the columns and rows of the grid with a space-separated list of values. The values represent the track size, and the space between them represents the grid line.

Values:

  • <track-size> - can be a length, a percentage, or a fraction of the free space in the grid (using the fr unit)
  • <line-name> - an arbitrary name of your choosing
.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}

Examples:

When you leave an empty space between the track values, the grid lines are automatically assigned numerical names:

.container{
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

Grid with auto named lines

But you can choose to explicitly name the lines. Note the bracket syntax for the line names:

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

Grid with user named lines

Note that a line can have more than one name. For example, here the second line will have two names: row1-end and row2-start:

.container{
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

If your definition contains repeating parts, you can use the repeat() notation to streamline things:

.container {
  grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

Which is equivalent to this:

.container {
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

The fr unit allows you to set the size of a track as a fraction of the free space of the grid container. For example, this will set each item to one third the width of the grid container:

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

The free space is calculated after any non-flexible items. In this example the total amount of free space available to the fr units doesn't include the 50px:

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}

grid-template-areas

Defines a grid template by referencing the names of the grid areas which are specified with the grid-area property. Repeating the name of a grid area causes the content to span those cells. A period signifies an empty cell. The syntax itself provides a visualization of the structure of the grid.

Values:

  • <grid-area-name> - the name of a grid area specified with grid-area
  • . - a period signifies an empty grid cell
  • none - no grid areas are defined
.container {
  grid-template-areas: 
    "<grid-area-name> | . | none | ..."
    "...";
}

Example:

.item-a {
  grid-area: header;
}
.item-b {
  grid-area: main;
}
.item-c {
  grid-area: sidebar;
}
.item-d {
  grid-area: footer;
}

.container {
  grid-template-columns: 50px 50px 50px 50px;
  grid-template-rows: auto;
  grid-template-areas: 
    "header header header header"
    "main main . sidebar"
    "footer footer footer footer";
}

That'll create a grid that's four columns wide by three rows tall. The entire top row will be comprised of the header area. The middle row will be comprised of two main areas, one empty cell, and one sidebar area. The last row is all footer.

Example of grid-template-areas

Each row in your declaration needs to have the same number of cells.

You can use any number of adjacent periods to declare a single empty cell. As long as the periods have no spaces between them they represent a single cell.

Notice that you're not naming lines with this syntax, just areas. When you use this syntax the lines on either end of the areas are actually getting named automatically. If the name of your grid area is foo, the name of the area's starting row line and starting column line will be foo-start, and the name of its last row line and last column line will be foo-end. This means that some lines might have multiple names, such as the far left line in the above example, which will have three names: header-start, main-start, and footer-start.

grid-template

A shorthand for setting grid-template-rows, grid-template-columns, and grid-template-areas in a single declaration.

Values:

.container {
  grid-template: none | subgrid | <grid-template-rows> / <grid-template-columns>;
}

It also accepts a more complex but quite handy syntax for specifying all three. Here's an example:

.container {
  grid-template:
    [row1-start] 25px "header header header" [row1-end]
    [row2-start] "footer footer footer" 25px [row2-end]
    / auto 50px auto;
}

That's equivalent to this:

.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "header header header" 
    "footer footer footer";
}

Since grid-template doesn't reset the implicit grid properties (grid-auto-columns, grid-auto-rows, and grid-auto-flow), which is probably what you want to do in most cases, it's recommended to use the grid property instead of grid-template.

grid-column-gap
grid-row-gap

Specifies the size of the grid lines. You can think of it like setting the width of the gutters between the columns/rows.

Values:

  • <line-size> - a length value
.container {
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}

Example:

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  grid-column-gap: 10px;
  grid-row-gap: 15px;
}

Example of grid-column-gap and grid-row-gap

The gutters are only created between the columns/rows, not on the outer edges.

grid-gap

A shorthand for grid-row-gap and grid-column-gap

Values:

  • <grid-row-gap> <grid-column-gap> - length values
.container {
  grid-gap: <grid-row-gap> <grid-column-gap>;
}

Example:

.container{
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  grid-gap: 10px 15px;
}

If no grid-row-gap is specified, it's set to the same value as grid-column-gap

justify-items

Aligns the content inside a grid item along the row axis (as opposed to align-items which aligns along the column axis). This value applies to all grid items inside the container.

Values:

  • start - aligns the content to the left end of the grid area
  • end - aligns the content to the right end of the grid area
  • center - aligns the content in the center of the grid area
  • stretch - fills the whole width of the grid area (this is the default)
.container {
  justify-items: start | end | center | stretch;
}

Examples:

.container {
  justify-items: start;
}

Example of justify-items set to start

.container{
  justify-items: end;
}

Example of justify-items set to end

.container{
  justify-items: center;
}

Example of justify-items set to center

.container{
  justify-items: stretch;
}

Example of justify-items set to stretch

This behavior can also be set on individual grid items via the justify-self property.

align-items

Aligns the content inside a grid item along the column axis (as opposed to justify-items which aligns along the row axis). This value applies to all grid items inside the container.

Values:

  • start - aligns the content to the top of the grid area
  • end - aligns the content to the bottom of the grid area
  • center - aligns the content in the center of the grid area
  • stretch - fills the whole height of the grid area (this is the default)
.container {
  align-items: start | end | center | stretch;
}

Examples:

.container {
  align-items: start;
}

Example of align-items set to start

.container {
  align-items: end;
}

Example of align-items set to end

.container {
  align-items: center;
}

Example of align-items set to center

.container {
  align-items: stretch;
}

Example of align-items set to stretch

This behavior can also be set on individual grid items via the align-self property.

justify-content

Sometimes the total size of your grid might be less than the size of its grid container. This could happen if all of your grid items are sized with non-flexible units like px. In this case you can set the alignment of the grid within the grid container. This property aligns the grid along the row axis (as opposed to align-content which aligns the grid along the column axis).

Values:

  • start - aligns the grid to the left end of the grid container
  • end - aligns the grid to the right end of the grid container
  • center - aligns the grid in the center of the grid container
  • stretch - resizes the grid items to allow the grid to fill the full width of the grid container
  • space-around - places an even amount of space between each grid item, with half-sized spaces on the far ends
  • space-between - places an even amount of space between each grid item, with no space at the far ends
  • space-evenly - places an even amount of space between each grid item, including the far ends
.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;	
}

Examples:

.container {
  justify-content: start;
}

Example of justify-content set to start

.container {
  justify-content: end;	
}

Example of justify-content set to end

.container {
  justify-content: center;	
}

Example of justify-content set to center

.container {
  justify-content: stretch;	
}

Example of justify-content set to stretch

.container {
  justify-content: space-around;	
}

Example of justify-content set to space-around

.container {
  justify-content: space-between;	
}

Example of justify-content set to space-between

.container {
  justify-content: space-evenly;	
}

Example of justify-content set to space-evenly

align-content

Sometimes the total size of your grid might be less than the size of its grid container. This could happen if all of your grid items are sized with non-flexible units like px. In this case you can set the alignment of the grid within the grid container. This property aligns the grid along the column axis (as opposed to justify-content which aligns the grid along the row axis).

Values:

  • start - aligns the grid to the top of the grid container
  • end - aligns the grid to the bottom of the grid container
  • center - aligns the grid in the center of the grid container
  • stretch - resizes the grid items to allow the grid to fill the full height of the grid container
  • space-around - places an even amount of space between each grid item, with half-sized spaces on the far ends
  • space-between - places an even amount of space between each grid item, with no space at the far ends
  • space-evenly - places an even amount of space between each grid item, including the far ends
.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;	
}

Examples:

.container {
  align-content: start;	
}

Example of align-content set to start

.container {
  align-content: end;	
}

Example of align-content set to end

.container {
  align-content: center;	
}

Example of align-content set to center

.container {
  align-content: stretch;	
}

Example of align-content set to stretch

.container {
  align-content: space-around;	
}

Example of align-content set to space-around

.container {
  align-content: space-between;	
}

Example of align-content set to space-between

.container {
  align-content: space-evenly;	
}

Example of align-content set to space-evenly

grid-auto-columns
grid-auto-rows

Specifies the size of any auto-generated grid tracks (aka implicit grid tracks). Implicit grid tracks get created when you explicitly position rows or columns (via grid-template-rows/grid-template-columns) that are out of range of the defined grid.

Values:

  • <track-size> - can be a length, a percentage, or a fraction of the free space in the grid (using the fr unit)
.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}

To illustrate how implicit grid tracks get created, think about this:

.container {
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px
}

Example of 2 x 2 grid

This creates a 2 x 2 grid.

But now imagine you use grid-column and grid-row to position your grid items like this:

.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b {
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}

Example of implicit tracks

We told .item-b to start on column line 5 and end at column line 6, but we never defined a column line 5 or 6. Because we referenced lines that don't exist, implicit tracks with widths of 0 are created to fill in the gaps. We can use grid-auto-columns and grid-auto-rows to specify the widths of these implicit tracks:

.container {
  grid-auto-columns: 60px;
}

Example of implicit tracks

grid-auto-flow

If you have grid items that you don't explicitly place on the grid, the auto-placement algorithm kicks in to automatically place the items. This property controls how the auto-placement algorithm works.

Values:

  • row - tells the auto-placement algorithm to fill in each row in turn, adding new rows as necessary
  • column - tells the auto-placement algorithm to fill in each column in turn, adding new columns as necessary
  • dense - tells the auto-placement algorithm to attempt to fill in holes earlier in the grid if smaller items come up later
.container {
  grid-auto-flow: row | column | row dense | column dense
}

Note that dense might cause your items to appear out of order.

Examples:

Consider this HTML:

<section class="container">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</section>

You define a grid with five columns and two rows, and set grid-auto-flow to row (which is also the default):

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: row;
}

When placing the items on the grid, you only specify spots for two of them:

.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}

Because we set grid-auto-flow to row, our grid will look like this. Notice how the three items we didn't place (item-b, item-c and item-d) flow across the available rows:

Example of grid-auto-flow set to row

If we instead set grid-auto-flow to column, item-b, item-c and item-d flow down the columns:

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: column;
}

Example of grid-auto-flow set to column

grid

A shorthand for setting all of the following properties in a single declaration: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, and grid-auto-flow. It also sets grid-column-gap and grid-row-gap to their initial values, even though they can't be explicitly set by this property.

Values:

.container {
    grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}

Examples:

The following two code blocks are equivalent:

.container {
  grid: 200px auto / 1fr auto 1fr;
}
.container {
  grid-template-rows: 200px auto;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas: none;
}

And the following two code blocks are equivalent:

.container {
  grid: column 1fr / auto;
}
.container {
  grid-auto-flow: column;
  grid-auto-rows: 1fr;
  grid-auto-columns: auto;
}

It also accepts a more complex but quite handy syntax for setting everything at once. You specify grid-template-areas, grid-template-rows and grid-template-columns, and all the other sub-properties are set to their initial values. What you're doing is specifying the line names and track sizes inline with their respective grid areas. This is easiest to describe with an example:

.container {
  grid: [row1-start] "header header header" 1fr [row1-end]
        [row2-start] "footer footer footer" 25px [row2-end]
        / auto 50px auto;
}

That's equivalent to this:

.container {
  grid-template-areas: 
    "header header header"
    "footer footer footer";
  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;    
}

Properties for the Children
(Grid Items)

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

Determines a grid item's location within the grid by referring to specific grid lines. grid-column-start/grid-row-start is the line where the item begins, and grid-column-end/grid-row-end is the line where the item ends.

Values:

  • <line> - can be a number to refer to a numbered grid line, or a name to refer to a named grid line
  • span <number> - the item will span across the provided number of grid tracks
  • span <name> - the item will span across until it hits the next line with the provided name
  • auto - indicates auto-placement, an automatic span, or a default span of one
.item {
  grid-column-start: <number> | <name> | span <number> | span <name> | auto
  grid-column-end: <number> | <name> | span <number> | span <name> | auto
  grid-row-start: <number> | <name> | span <number> | span <name> | auto
  grid-row-end: <number> | <name> | span <number> | span <name> | auto
}

Examples:

.item-a {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start
  grid-row-end: 3
}

Example of grid-row/column-start/end

.item-b {
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2
  grid-row-end: span 2
}

Example of grid-row/column-start/end

If no grid-column-end/grid-row-end is declared, the item will span 1 track by default.

Items can overlap each other. You can use z-index to control their stacking order.

grid-column
grid-row

Shorthand for grid-column-start + grid-column-end, and grid-row-start + grid-row-end, respectively.

Values:

  • <start-line> / <end-line> - each one accepts all the same values as the longhand version, including span
.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

Example:

.item-c {
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}

Example of grid-column/grid-row

If no end line value is declared, the item will span 1 track by default.

grid-area

Gives an item a name so that it can be referenced by a template created with the grid-template-areas property. Alternatively, this property can be used as an even shorter shorthand for grid-row-start + grid-column-start + grid-row-end + grid-column-end.

Values:

  • <name> - a name of your choosing
  • <row-start> / <column-start> / <row-end> / <column-end> - can be numbers or named lines
.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}

Examples:

As a way to assign a name to the item:

.item-d {
  grid-area: header
}

As the short-shorthand for grid-row-start + grid-column-start + grid-row-end + grid-column-end:

.item-d {
  grid-area: 1 / col4-start / last-line / 6
}

Example of grid-area

justify-self

Aligns the content inside a grid item along the row axis (as opposed to align-self which aligns along the column axis). This value applies to the content inside a single grid item.

Values:

  • start - aligns the content to the left end of the grid area
  • end - aligns the content to the right end of the grid area
  • center - aligns the content in the center of the grid area
  • stretch - fills the whole width of the grid area (this is the default)
.item {
  justify-self: start | end | center | stretch;
}

Examples:

.item-a {
  justify-self: start;
}

Example of justify-self set to start

.item-a {
  justify-self: end;
}

Example of justify-self set to end

.item-a {
  justify-self: center;
}

Example of justify-self set to center

.item-a {
  justify-self: stretch;
}

Example of justify-self set to stretch

To set alignment for all the items in a grid, this behavior can also be set on the grid container via the justify-items property.

align-self

Aligns the content inside a grid item along the column axis (as opposed to justify-self which aligns along the row axis). This value applies to the content inside a single grid item.

Values:

  • start - aligns the content to the top of the grid area
  • end - aligns the content to the bottom of the grid area
  • center - aligns the content in the center of the grid area
  • stretch - fills the whole height of the grid area (this is the default)
.item {
  align-self: start | end | center | stretch;
}

Examples:

.item-a {
  align-self: start;
}

Example of align-self set to start

.item-a {
  align-self: end;
}

Example of align-self set to end

.item-a {
  align-self: center;
}

Example of align-self set to center

.item-a {
  align-self: stretch;
}

Example of align-self set to stretch

To align all the items in a grid, this behavior can also be set on the grid container via the align-items property.


This article was ported over from Chris House's guide, by Chris himself, who is keeping both up-to-date.

Comments

  1. User Avatar
    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.

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

    header{
    
    /* shorthand would define top/bottom margin for each row*/
    grid-row-margin:15px;
    
    /*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;
    }
    

    thoughts?

    • User Avatar
      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. User Avatar
    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. User Avatar
    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

    • User Avatar
      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. User Avatar
    Millennium Outlaw
    Permalink to comment#

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

  5. User Avatar
    Senpai
    Permalink to comment#

    Why the hell isn’t this widely supported yet?
    ;(

  6. User Avatar
    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.

    • User Avatar
      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. User Avatar
    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.

    • User Avatar
      Al Street
      Permalink to comment#

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

  8. User Avatar
    Paulo Sergio

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

  9. User Avatar
    Thillai
    Permalink to comment#

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

  10. User Avatar
    Juan Carlos
    Permalink to comment#

    Every browser supports this grid property?

    • User Avatar
      Dave Mackey
      Permalink to comment#

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

  11. User Avatar
    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.

  12. User Avatar
    Juan
    Permalink to comment#

    Is there a polyfill for this module yet?

  13. User Avatar
    Evert
    Permalink to comment#

    So, how would one go about making full-width background colors on headers and footers while still maintaining a max/min width on the (centered) content.
    That is a very common layout-pattern; I’d like to see it reproduced with grids?

  14. User Avatar
    SelenIT
    Permalink to comment#

    The ‘grid-template’ shorthand has been recently removed from the spec draft in favor of ‘grid’ super-shorthand: https://bugzilla.mozilla.org/show_bug.cgi?id=1253529#c0. Shouldn’t the article be updated again?

  15. User Avatar
    Vuchkov.biz
    Permalink to comment#

    Whow… it is working like a magic… Congratulations!

  16. User Avatar
    Bitcollage
    Permalink to comment#

    Best tutorial ever, thank you :)

  17. User Avatar
    Andrei
    Permalink to comment#

    I love the Grid Layout. But, but, but reality is it’s not supported well. How much time (years) you think it will take so we can use it across the most popular web-browsers?

    • User Avatar
      Denis
      Permalink to comment#

      I am actually curious about the same thing.

    • User Avatar
      Aaron

      I’ve been thinking the same thing, and it appears that support has in fact diminished since 2014-ish when these articles were written. http://caniuse.com/#feat=css-grid states that FF/Chrome have no intention of supporting it, Safari has left it behind and microsoft has gone to prefixing it.

    • User Avatar
      Rich Morris
      Permalink to comment#

      As it’s not supported by default in any browsers at the moment caniuse.com will show it as not supported, but this page shows a more accurate state of play:
      http://gridbyexample.com/browsers/

      Hopefully 2017 will be there year this gets supported by default.

  18. User Avatar
    Sam

    As someone who has used WPF / Silverlight Grids a lot and can’t wait to use CSS Grids, I’m curious about the following:

    Can a column or row be defined that sizes to the minimum required for the width or height of its children? From the article it looks like ‘auto’ means *-sizing in WPF speak, meaning take up all available space, not the minimum amount of space required which is what Auto-sizing means in WPF.
    Is it possible to use minimum / maximum width settings on grid tracks if they are dynamically sized, irrespective of children? EG you want a column that stretches to fit available space but should have a minimum width of 100px even if empty.

    • User Avatar
      Manuel Rego

      For the minimum required width or height you can use min-content (or max-content for the maximum):
      E.g. grid-template-columns: min-content 200px max-content;

      About the minimum-maximum size settings, you could use minmax() function.
      E.g. grid-template-columns: minmax(100px, 1fr);

  19. User Avatar
    Lee Borowiak
    Permalink to comment#

    Interesting article.

    if you’re looking for a super simple Responsive CSS Grid, check this one out:
    https://codecanyon.net/item/responsive-html5-css-grid/4928861?ref=CSSGrid

    Lee.

  20. User Avatar
    geligelu
    Permalink to comment#

    I can’t help but notice from the spec that there seems to be a lot of similarities with this and the much maligned table layout. Was using tables for layout just so hated because it was meant for data, not layout?

  21. User Avatar
    Carlos Rodiguez
    Permalink to comment#

    This grid system its just like wpf but more flexible for people that have worked with wpf its easy to understand and it help to move to new tecnology like asp.net core.

  22. User Avatar
    Jan
    Permalink to comment#

    Great introduction!
    I found one (well known) issue:
    If you want to use % value for height of a child inside a grid-cell, you have to set height:100% for the cell. Otherwise the height of the viewport is taken. You may know this behaviour from body{ height:100%;}

  23. User Avatar
    Marco
    Permalink to comment#

    I really can’t wait for this spec to become standard.
    Also, I must have a problem with github because every single blog talking about css grid forwards to Remy’s PF, but I am unable to get a result with those browsers that don’t have the flag.
    Maybe I just don’t understand which one, in github, is the actual .js file to use…

  24. User Avatar
    Marco
    Permalink to comment#

    Anyone knows of a possible malfunction of grid-column-gap/grid-row-gap in François REMY’s polyfill?
    Or it’s me? :-)

  25. User Avatar
    Rafi
    Permalink to comment#

    Awesome. I hope this specs gets out soon and it is adopted by browsers fast. Then there would be no CSS haters.

  26. User Avatar
    Marcelo Lazaroni de Rezende Junio
    Permalink to comment#

    Great article! It’s just a bit confusing in some places, like under justify-items where it uses column axis to refer to the horizontal axis and other places where it uses row-axis to refer to the vertical axis. The images clarify the terms but changing that would make things easier.

    Fantastic resource, anyway.

    • User Avatar
      Zambonifofex
      Permalink to comment#

      I might be wrong, but I think that “column axis” might be able to mean either “horizontal axis” or “vertical axis” depending on the writing mode.

  27. User Avatar
    Orlando
    Permalink to comment#

    Hi there.

    How is this better than the already available Flexbox standard?

  28. User Avatar
    Gavin
    Permalink to comment#

    Is it me or does chrome not support
    grid-template-columns and grid-template-rows even with the experimental flag on?

  29. User Avatar
    AVJ
    Permalink to comment#

    Hi,

    Thanks for a great article.

    I think that order of the arguments of the shorthand grid-gap are reversed, it should be row columninstead of column row

    From MDN:

    The grid-gap CSS property is a shorthand property for grid-row-gap and grid-column-gap specifying the gutters between grid rows and columns.

    If <‘grid-column-gap’> is omitted, it’s set to the same value as <‘grid-row-gap’>.

    I tried in both Firefox and Chrome and this is the way they do it.

    • User Avatar
      Chris Coyier
      Permalink to comment#

      You’re right it’s row first, column second. I got that updated.

  30. User Avatar
    MaxArt
    Permalink to comment#

    Two small remarks:

    grid-template-columns: <track-size> … | <line-name> <track-size> …;

    Actually you can begin and end the value of this property with line names.

    . – a period signifies an empty grid cell

    This doesn’t mean the cell will stay empty – it just doesn’t belong to a named region. You can still fill it with content, though.

  31. User Avatar
    Chris
    Permalink to comment#

    Great info, but I seem to be having an issue getting rows to dynamically resize based on content when using firefox.

    Is this a known issue? Is there a workaround I should be using?
    Thanks in advance,
    –Chris

  32. User Avatar
    Marco
    Permalink to comment#

    CSS Grid Layout Module Level 1 is now (as of Feb 9th 2017) W3C Candidate Recommendation :-)

    Yupeeeeee!!!

  33. User Avatar
    Elias
    Permalink to comment#

    I used this successfully with vh attribute to define row heights. Eg.

    .grid {
        display: grid;
        grid-template-columns: 40px 50px auto 50px 40px;
        grid-template-rows: auto 85vh auto;
    }
    

    This gave me a nice footer in the bottom.

  34. User Avatar
    Daniel Murphy
    Permalink to comment#

    This would be a great addition to use hand-in-hand with flexbox – each serving their own purpose. I suppose you could easily use css to change a grid into a flexbox based on media queries. The grid gives us a reason to build our website kind of like back when sites were designed using tables. The only reason why we still don’t to that today is because using the table tag paints you in a corner, whereas the grid is based on css – not a tag (in addition to being non-mobile-responsive). Please let me know if anyone disagrees.

  35. User Avatar
    Chen Hui Jing
    Permalink to comment#

    Hello, there is an issue with the axis descriptions for some of the alignment properties. The ones for justify-items and align-items are correct but the remaining 4 are not. The justify-* properties are aligned along the row-axis (inline axis) and the align-* properties are aligned along the column-axis (block axis).

  36. User Avatar
    XCanG
    Permalink to comment#

    Hello! I’am curious how to propery limit one cell which have another subgrid if content in it expand that cell/subgrid? For example CSS for grid:

    width: 100vw;
    height: 100vh;
    display: grid;
    grid-template-columns: 40% [center] 40%; /*2 columns*/
    grid-template-rows: repeat(3, 1fr [row-start]) 10%; /*for test I use 4 rows*/
    grid-gap: 10px;
    justify-items: stretch;
    justify-content: space-around;
    

    CSS for subgrid, what one of a cell of a grid:

    display: grid; /*Firefox Nightly doesn't have "subgrid", so I define it as grid*/
    grid-auto-flow: column;
    grid-auto-columns: 20px;
    grid-template-columns: 20px;
    grid-gap: 2px;
    justify-content: space-evenly;
    overflow-x: auto;
    text-align: center;
    

    And it have HTML:

    < div style="background: rgba(80,150,220,.2);">1< /div>
    < div style="background: rgba(80,150,220,.2);">2< /div>
    ...
    < div style="background: rgba(80,150,220,.2);">50< /div>
    

    (space because html deleted)

    So that 50 elements make it wider and generate scrollbar on a page. If I try to define max-width and overflow-x, so first 4 elements will be hidden (but latest – not). It strange, why?

  37. User Avatar
    fuji
    Permalink to comment#

    The text inside the cell doesn’t start from new line according to the grid size, but expands outside the grid and makes vertical scroll…

  38. User Avatar
    Jarda Fišer
    Permalink to comment#

    Awesome article. Thanks for this cookbook. But I have one concern. It is clear that you can use px, maybe EMs and REMs too, but what about calc()? Can you use it to define dynamic columns?

  39. User Avatar
    Thiago Lagden
    Permalink to comment#

    I always used the flexbox’s guide…
    Now, you did this wonderful guide
    Thanks Chris!!

  40. User Avatar
    Stephan
    Permalink to comment#

    Might be silly question but I am somewhat confused. Say if I have a single page consisting of 3 columns and 2 columns and full width layouts, for instance something like this:

    How will this be defined in grid?

    Ps. I can’t ge the markdown working correctly :| Help? :)

  41. User Avatar
    deos
    Permalink to comment#

    great guide, but it is missing the auto-fill and auto-fit options for repeat(), could you please add those?

    https://drafts.csswg.org/css-grid/#auto-repeat

  42. User Avatar
    Michael Morris
    Permalink to comment#

    Awesome article, but one quibble. CSS grids is a 3D layout system once z-index is thrown into the mix. This allows background elements to be attached according to the grid lines.

  43. User Avatar
    Matt
    Permalink to comment#

    How can I make elements square?
    if I have

    .grid {
    grid-template: repeat(4, 25%);
    }

    Can I make the Row heights match the columns widths somehow?

  44. User Avatar
    Ben McFerren
    Permalink to comment#

    How can you use grid-auto-flow to make the unexpected children invisible instead of positioned with row | column | row dense | column dense ?

  45. User Avatar
    Albert Bond

    Hi friends,
    i have a grid layout

    .container{
       display: grid;
        display: -ms-grid;
        grid-template-columns: 250px 1fr;
        grid-template-rows: 100% 100%;}
    

    this, good, and the divs alright,
    but if i hide the first column with javascript, the second column take te position of the first.

    Ex:

    [visible div 1] [              visible div 2                      ]
    

    When hide the div 1, the div 2 it remains as:

    [visible div 2]----------dead remanin space-----------------
    

    and not this

    [                            visible div 2                                  ]
    

    exist possibility of fix this??

    I have the same page whith flexbox and works, but not with grid.

  46. User Avatar
    Markus

    Hello.

    I use following CSS:

    .wrapper {
      display: grid;
      grid-template-columns: 4fr 8fr;
      grid-template-rows: auto;
      grid-template-areas:
      "header content"
      "footer content";
    }
    

    And now I want to have the content (e.g. navigation) of the footer at the bottom of the footer area. I have try it with align-self: end; but it doesn’t make what I need.

    Hope someone can help.

  47. User Avatar
    Bob

    Excellent article. I’m sure I’ll wear this one out like i have the complete guide to Flexbox. Simple question, does anyone know if you can outline the grid? I feel that would go a long way to demystifying this as I’m learning.

  48. User Avatar
    Daniel

    This is amazing to use and very informative. Its so easy to make layouts, when you get the knack of it I think you could make a header, 3-cols, footer layout in under 4mins.

    However while playing around I haven’t grasped how to change the width of a single column. Is there such a thing as a “grid-column-width” sort of property for children?

    For example if you have primary, secondary and content columns and wanted to change the width of say the secondary column using the :checked psudo-selector so it slides in and out of view (and updates the width of the content column appropriately) how would you change the width of it?

    I’m using “grid-template-columns: 100px 200px auto” which is obviously on the parent and defining grid-areas but I want to change the width of just a single column.

    Hope I’ve explained this well enough.

  49. User Avatar
    Phil
    Permalink to comment#

    This is a great resource. I’m wondering how people are handling dynamic row height on resize of the view port. As far as I can tell there is no way to keep the proportions of the grid cells.

  50. User Avatar
    GonArrivi
    Permalink to comment#

    Amazing article just added to my references list. Thanks!

  51. User Avatar
    Tom
    Permalink to comment#

    Thanks for this very useful article!

    I have a question about styling grid rows > in this case altering background color each row.
    I made a ul > li list with a lot of items. The col count depends on the width of the viewport. Max. 5 cols on witdh more than 1200px, 1 col on smartphone. Now I need dynamic function to alter the background color for every even/odd row. How can I do this?

    Well, when on viewport 1200px + I have 5 cols. If I want to have another background color for the odd rows I can write CSS something like this >
    .cols li:nth-child(n+6):nth-child(-n+10)
    But here I have to define each row by it’s own code. Is there another solution via CSS or do I have to use JS to add classes dynamically?

    thx, Tom

  52. User Avatar
    Anup
    Permalink to comment#

    Why css grid method doesn’t work when I apply masonry js?

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag