Skip to content
GitHub

CSS Grid Layout

Switch to Zen Mode
  • Two-dimensional layout control (rows AND columns),
  • Precise placement of elements,
  • Easy creation of complex layouts,
  • Dynamic re-ordering of content based on media queries,
  • Built-in support for responsive design,
  • Reduced need for layout frameworks and extra markup.

To create a grid layout, you first need to define a container as a grid by applying the display: grid; or display: inline-grid; property to a parent element:

.container {
display: grid;
}
css

.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 20px; /* Adds gap between both rows and columns */
}
css

To set different gaps for rows and columns:

.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 40px;
}
css

Use the grid-template-columns and grid-template-rows properties to define the size and number of columns and rows.

You can define fixed-size grid tracks (rows and columns) using various units:

.container {
display: grid;
grid-template-columns: 100px 200px 100px;
grid-template-rows: 50px 100px;
}
css

This creates a grid with:

  • Three columns of 100px, 200px, and 100px widths
  • Two rows of 50px and 100px heights

The fr unit represents a fraction of the available space in the grid container:

.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: auto;
}
css

This creates a grid where:

  • The total width is divided into 4 equal parts (1+2+1)
  • The first column gets 1/4 of the space
  • The second column gets 2/4 (or 1/2) of the space
  • The third column gets 1/4 of the space

For large grids, you can use the repeat() function:

.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* Same as: 1fr 1fr 1fr */
grid-template-rows: repeat(2, 100px); /* Same as: 100px 100px */
}
css

The repeat() function takes two arguments:

  1. The number of times to repeat
  2. The pattern to repeat

The minmax() function defines a size range:

.container {
display: grid;
grid-template-columns: 1fr minmax(200px, 500px) 1fr;
}
css

This creates a middle column that:

  • Will never be smaller than 200px
  • Will never be larger than 500px
  • Will grow and shrink within those constraints

For responsive design, auto-fill and auto-fit are useful:

.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
css

This creates as many 200px+ columns as can fit in the container.

  • auto-fill: Creates as many tracks as possible, even if they’re empty
  • auto-fit: Collapses empty tracks and stretches existing tracks to fill the space

For implicitly created grid tracks:

.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px; /* Any new rows will be 100px tall */
}
css
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: auto;
}
css
  • 1fr 2fr 1fr means the grid will have three columns. The first and third columns will take 1 fraction of available space each, while the second column will take 2 fractions.
  • auto means the row height will adjust automatically based on the content.

Once your grid is defined, you can position grid items using various methods:

Grid lines are automatically numbered starting from 1:

.item {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 4;
}
css

This places the item:

  • From column line 1 to column line 3 (spanning 2 columns)
  • From row line 2 to row line 4 (spanning 2 rows)
.item {
grid-column: 1 / 3; /* Start at line 1, end at line 3 */
grid-row: 2 / 4; /* Start at line 2, end at line 4 */
}
css

Even shorter using the unified grid-area property:

.item {
/* Format: row-start / column-start / row-end / column-end */
grid-area: 2 / 1 / 4 / 3;
}
css
.item {
grid-column: 1 / span 2; /* Start at line 1 and span 2 columns */
grid-row: span 2 / 4; /* End at line 4 and span 2 rows upward */
}
css

You can count grid lines from the end using negative numbers:

.item {
grid-column: 1 / -1; /* Spans from first line to last line */
}
css

You can also assign a name to grid areas and place grid items in those areas:

.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
css

This creates a classic page layout with header, footer, main content and sidebars.

You can leave cells empty using a period (.):

grid-template-areas:
"header header header"
"sidebar content . "
"footer footer footer";
css

In this example, the top-right cell in the middle row is left empty.


CSS Grid has powerful alignment capabilities, divided into two categories:

.container {
/* Horizontal alignment */
justify-items: start | end | center | stretch;
/* Vertical alignment */
align-items: start | end | center | stretch;
/* Shorthand for both */
place-items: <align-items> <justify-items>;
}
css
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: <align-self> <justify-self>;
}
css

If the grid tracks don’t use all available space:

.container {
/* Horizontal alignment of all tracks */
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
/* Vertical alignment of all tracks */
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
/* Shorthand for both */
place-content: <align-content> <justify-content>;
}
css
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr; /* Switches to 1 column layout */
}
}
css
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
css

This creates a responsive grid where:

  • Each column is at least 250px wide
  • Columns expand to fill available space
  • The number of columns adjusts automatically as the viewport changes
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
@media (min-width: 768px) {
.container {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
}
@media (min-width: 1024px) {
.container {
grid-template-columns: 200px 1fr 200px;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
}
}
css

Grid and Flexbox are complementary, not competing layout systems. Here’s when to use each:

  • Creating two-dimensional layouts (rows AND columns)
  • Working with the overall page layout
  • Precise placement of elements is needed
  • Creating complex, asymmetrical layouts
  • Designing from the “outside in” (defining the container first)
  • Creating one-dimensional layouts (either rows OR columns)
  • Distributing space among elements of unknown size
  • Aligning items within a container
  • Working with content flow rather than explicit placement
  • Designing from the “inside out” (letting the content dictate the layout)

  1. MDN CSS Grid Layout
  2. CSS Grid Layout Guide
  3. An Interactive Guide to CSS Grid
  4. MDN CSS Grid Guide