Once a container has display: grid, the next question is how many columns it has and how wide each one is. That is exactly what grid-template-columns is for: without it, a grid defaults to a single column as wide as the container, which is rarely useful.
This property accepts several kinds of values at once, fixed sizes in pixels, fractions with the fr unit, percentages, or the repeat() function to avoid typing the same value over and over. It has a mirror property, grid-template-rows, which does the exact same job for rows.
Definition
grid-template-columns sets the number of columns in a CSS grid and the width of each one, on an element that has CSS Grid turned on. Each value in the list maps to one column: three values create three columns, a single value creates a single column. It is the most fundamental property for drawing the structure of a grid, even before placing a single item inside it.
Syntax and value types
.grid {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 80px auto;
}Here, the first column is a fixed 200 pixels, and the next two share the remaining space equally thanks to the fr unit unit. Rows follow the same logic: a first row of 80 pixels, then a row whose height adjusts to its content with auto. Nothing forces you to mix units, a grid in fixed pixels or entirely in fr is just as valid.
| Value | Effect |
|---|---|
200px | Fixed width column, never shrinks |
1fr | Column that takes a fraction of the remaining space |
auto | Column that sizes itself to its content |
repeat(3, 1fr) | Three identical columns, without typing them out |
Avoiding repetition with repeat()
Writing grid-template-columns: 1fr 1fr 1fr 1fr 1fr for five identical columns works, but quickly becomes hard to read and error prone whenever you need to adjust it. The repeat() and minmax() function shortens that list to repeat(5, 1fr), with exactly the same result.
.grid {
grid-template-columns: repeat(5, 1fr);
}Combining fixed sizes with repetition
.layout {
grid-template-columns: 220px repeat(3, 1fr);
}repeat() does not force a choice between a fully repeated grid and one written entirely by hand, the two combine in the same declaration. Here, a fixed first column of 220 pixels acts as a sidebar, followed by three equal columns generated by repeat(3, 1fr). It is a very common pattern for a layout with one distinct zone, a menu or a filter panel, next to a regular main content area.
This flexibility avoids having to pick between two radically different approaches based on how complex the grid gets. A grid can perfectly well start simple, with a few columns in pixels, then evolve into a mix of fixed values and repeat() as its structure becomes clearer, without ever needing to be rewritten from scratch.
A common trap: forgetting implicit rows
grid-template-columns only sets the columns you explicitly declare. If content overflows those columns, the grid does not create new columns on its own: it stacks the overflow into new rows, called implicit rows, whose height follows a different rule controlled by grid-auto-rows.
grid-template-columns, with the implicit columns the grid could create in the other direction. By default, Grid adds rows for extra content, never columns: changing that fill direction requires the grid-auto-flow property.Frequently asked questions
fr units in the same declaration?Yes, with no issue at all. A declaration like grid-template-columns: 100px 20% 1fr is perfectly valid: the first column is fixed, the second follows a percentage of the container, and the third takes whatever is left. It is even a common combination for a fixed sidebar next to a flexible content area.
Extra children do not disappear. They get placed into new implicit rows, reusing the same column pattern you declared. With three columns and seven children, you end up with two full rows and a third row holding a single item.
grid-template-columns work without grid-template-rows?Yes, the two properties are independent. Without grid-template-rows, row height adjusts automatically to the tallest content in each row, which works well for the majority of layouts where only column width needs to be precise.