grid

Avatar of Mojtaba Seyedi
Mojtaba Seyedi on (Updated on )

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

The grid CSS property is a shorthand that allows you to set all the implicit and the explicit grid properties in a single declaration.

.grid-container {
  display: grid;
  grid: auto-flow dense / repeat(5, 150px);
}

The above example sets grid-template-columns to repeat(5, 150px) and grid-auto-flow to row dense which creates a grid container that has five explicit columns and auto-repeated rows.

Constituent properties

As mentioned, the grid property is a shorthand that combines multiple properties. This is the list of all its sub-properties:

That’s a lot of properties for a single shorthand! As you might imagine, some declarations can get super complex super fast. We’ll cover the syntax and values, then get into some examples to help you use grid them effectively.

Syntax

The grid property syntax matches the grid-template property, plus an additional syntax for defining auto-flow grids:

grid: <'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
  • Initial value: as each of the properties of the shorthand.
  • Applies to: grid containers
  • Inherited: no
  • Computed value: as specified, but with relative lengths converted into absolute lengths for grid-template-columns and grid-template-rows and the percentage as specified or the absolute length for grid-auto-rows and grid-auto-columns properties.
  • Animation type: simple list of length, percentage, or calc, provided the only differences are in the values of the length, percentage, or calc components in the list for grid-template-columns and grid-template-rows and discrete for the other properties of the shorthand.

Values

/* <'grid-template'> values */
grid: "header header header"
      "sidebar main main"
      ". footer footer";
grid: 100px 1fr / 300px 1fr;
grid: [line1] 100px / [sidebar] 250px [content] 1fr;
grid: repeat(4, auto) / repeat(4, minmax(100px, 1fr));
grid: [row1-top] "header header" 100px [row1-bottom]
      "sidebar main" 1fr [row2-bottom] / [col1-start] 300px [col1-end] 1fr;

/* <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? values */
/* explicit rows / auto generated columns */
grid: 50% / auto-flow dense;
grid: 100px 1fr / auto-flow;
grid: repeat(5, [line] 20rem) / auto-flow 15rem;
grid: min-content minmax(200px, 1fr) / auto-flow dense 300px;

/* [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'> values */
/* auto generated rows / explicit columns */
grid: auto-flow dense / 50%;
grid: auto-flow / 100px 1fr;
grid: auto-flow 15rem / repeat(5, [line] 20rem);
grid: auto-flow dense 300px / min-content minmax(200px, 1fr);

/* Global values */
grid: inherit;
grid: initial;
grid: revert;
grid: revert-layer;
grid: unset;

none

This is the default value. none sets all sub-properties to their initial values which means there are no named grid areas, and no explicit grid tracks that this property defines on the grid container.

It also means that grid tracks are implicitly generated, and sized by the grid-auto-columns and grid-auto-rows properties — both of which the none keyword sets to auto and the auto-placement algorithm is set to the initial value, which is row.

grid: none;

/* basically the same as saying */
grid-template-rows: none;
grid-template-columns: none;
grid-template-areas: none;
grid-auto-flow: row;
grid-auto-rows: auto;
grid-auto-columns: auto;

<'grid-template'>

You can use the grid property as grid-template to define explicit rows, columns, and areas.

Here, we describe how this syntax works but you can refer to the grid-template` property for complete information.

<'grid-template-rows'> / <'grid-template-columns'>

This form of the grid syntax defines rows and columns on a grid container in a single declaration while setting the grid-template-areas value to none. We split the values with a slash (/) in between them like so:

.grid-container {
  display: grid;
  grid: min-content 1fr / 200px 1fr 200px;
}

…which is equivalent to writing this without a shorthand:

.grid-container {
  display: grid;
  grid-template-rows: min-content 1fr;
  grid-template-columns: 200px 1fr 200px;
  grid-template-areas: none;
}

The order matters. The values before the slash set the grid-template-rows and the values after the slash set the grid-template-columns property.

Here is another example where explicit line names are used to define our grid:

/* One row of 100px and two columns of 250px and 1fr: */
.grid-container {
  display: grid;
  grid: [line1] 100px / [sidebar] 250px [content] 1fr;
}

…which, again, is equivalent to writing it this way without the shorthand:

.grid-container {
  display: grid;
  grid-template-rows: [line1] 100px;
  grid-template-columns: [sidebar] 250px [content] 1fr;
  grid-template-areas: none;
}
[ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?

The grid property also accepts a syntax that lets us explicitly specify the grid columns, rows, and areas at the same time.

grid:
  "header  header"
  "sidebar main"   1fr
  "footer  footer" min-content
  / 200px   1fr;

/* Basically the same as: */
grid-template-areas:  
  "header  header"
  "sidebar main"
  "footer  footer";
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr min-content;

header, sidebar, main, and footer are the names of the grid areas for a grid container. The number of names inside each string specifies the number of columns (which is two on each row in the example above).

The values after the columns — like 1fr and min-content above — represent the <track-size> for each row. If we don’t specify a track size on a row, as in the first row of the example above, the size of that row is set to auto.

The last line of the example contains a forward slash (/) followed by two length values. Those set the column sizes. And since we have two columns on each row, we need to provide two sizes. We’ve set the first column to 200px wide and the second row to 1fr.

The length value on a row sets that row’s height. The values on the last line after the slash set the width of the columns.

Be cautious when using the repeat() function. It wasn’t designed to work with the <'grid-template'> syntax of grid property! The idea is that repeat() would get in the way of being able to write things cleanly where everything can be lined up with whitespace — sort of like a simple visualization of the grid.

.grid {
  display: grid;
  grid: "header  header"
         "sidebar main"   1fr
         "footer  footer" min-content
         / 200px   1fr;
}

Note that repeat() is not allowed only in this syntax but you can use it in other syntax versions of the grid property.

<'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>?

This syntax forces you to define the rows explicitly, but on the other hand, the columns have to be declared implicitly. You need to write the value of grid-template-rows on the left side of the slash and add auto-flow keyword to the right side, which means the grid-auto-flow is set to column.

grid: 100px 1fr / auto-flow;

Also, you can add the dense keyword to the right side to apply the dense auto-placement algorithm:

grid: 100px 1fr / auto-flow dense;

And, in case you want to set the size of your implicit columns by the grid-auto-columns property, you can add the value to the right side:

grid: 100px 1fr / auto-flow dense 250px;

/* without dense */
grid: 100px 1fr / auto-flow 250px;

If you omit the dense value, grid-auto-columns will reset to auto, which is its initial value. And, since we are using grid shorthand property, all of the other sub-properties that we don’t set any values for will also be set to their initial values.

grid: 100px 1fr / auto-flow;

/* is equivalent to: */
grid-template-rows: 100px 1fr;
grid-template-columns: none; /* cannot be set in this syntax */
grid-template-areas: none; /* cannot be set in this syntax */
grid-auto-rows: auto; /* cannot be set in this syntax */
grid-auto-columns: auto;
grid-auto-flow: column; /* can only add dense */

As mentioned before, this syntax forces a grid with explicit rows and implicit columns — that’s why there are some limitations with the values you see in the code above. For example, the grid-template-columns and the grid-template-areas declarations define an explicit grid, which is unallowed in this syntax.

[auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>

As opposed to the previous syntax, this syntax forces you to define the columns explicitly, but on the other hand, the rows have to be declared implicitly. In other words, you need to write the value of grid-template-columns on the right side of the slash and add auto-flow keyword to the left side, which means the grid-auto-flow is set to row.

Let’s see an example:

grid: auto-flow / 100px 1fr;

You can add the dense keyword to the left side to apply the dense auto-placement algorithm:

grid: auto-flow dense / 100px 1fr;

And, in case you want to set the size of your implicit rows by the grid-auto-rows property, you can add the value to the left side:

grid: auto-flow dense 250px / 100px 1fr;

/* without dense */
grid: auto-flow 250px / 100px 1fr;

If you omit the dense value, grid-auto-rows will reset to auto, which is its initial value. And, since we are using grid shorthand property, all of the other sub-properties that we don’t set any values for will also be set to their initials.

grid: auto-flow / 100px 1fr;

/* is equivalent to: */
grid-template-columns: 100px 1fr;
grid-template-rows: none; /* cannot be set in this syntax */
grid-template-areas: none; /* cannot be set in this syntax */
grid-auto-columns: auto; /* cannot be set in this syntax */
grid-auto-rows: auto;
grid-auto-flow: row; /* can only add dense */

As mentioned before, this syntax forces a grid with explicit rows and implicit columns and that’s why there are some limitations with the values you see in the code above. For example, the grid-template-rows and the grid-template-areas declarations define an explicit grid, which is unallowed in this syntax.

The grid shorthand does not reset gap properties

In the first draft of CSS Grid Specifications, the grid property was used to reset the gutter properties too, but that changed in 2017. So, grid property no longer affects the gaps in a grid layout.

Example

Consider a gallery with eight columns and an unknown number of rows. Odd rows are 100 pixels tall and even rows are 200 pixels tall. Also, some images need to display at a larger size than the others and we don’t want any holes to appear between the items.

Since the columns are explicitly given, we start establishing our grid with the following code:

.gallery {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 1rem;
}

As for the rows, we can’t set them explicitly since we don’t know how many of them we need.

Also, as explained above, there needs to be a repeatable and alternating pattern of 100px and 200px row sizes. We set the grid-auto-rows like this:

.gallery {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-auto-rows: 100px 200px;
  gap: 1rem;
}

.gallery li:nth-child(2),
.gallery li:nth-child(4),
.gallery li:nth-child(6) {
  grid-column: span 2;
  grid-row: span 2;
}
A gallery created with CSS Grid. It has eight explicitly-defined columns using grid-template-columns and rows are auto-generated with their size specified by the grid-auto-rows property.

To remove the empty spaces in the above grid we set grid-auto-flow to dense:

.gallery {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-auto-rows: 100px 200px;
  grid-auto-flow: dense;
  gap: 1rem;
}

And we have what we want:

A dense grid of differently sized images to form a gallery.
We set the grid-auto-flow property to dense in order to make the auto-placement algorithm to do the back-tracking to find and fill holes with smaller items that come later in the grid.

We built all this to show you the magic of defining the whole scenario in a single declaration, thanks to the grid property.

.gallery {
  display: grid;
  grid: auto-flow dense 100px 200px / repeat(8, 1fr);
  gap: 1rem;
}

Also, check out the grid-template property for more examples of <'grid-template'> syntax form of the grid property.

Browser support

Specification