CSS grid-template-columns
grid-template-columns sets how many columns a grid has and how wide each one
is, with one value per column. 240px 2fr 1fr is a fixed sidebar, then two
fluid columns with the first twice as wide as the second.
The editor below uses exactly that. Change the values in the Tracks panel and watch the columns respond. To start from nothing, use the CSS grid generator.
Named areas. The CSS is a picture of the layout, and only the properties that actually change get repeated inside each media query.
.columns {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
gap: 16px;
grid-template-areas:
"nav"
"main"
"aside";
}
.columns > .nav { grid-area: nav; }
.columns > .main { grid-area: main; }
.columns > .aside { grid-area: aside; }
@media (min-width: 640px) {
.columns {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"nav nav"
"main aside";
}
}
@media (min-width: 1024px) {
.columns {
grid-template-columns: 240px 2fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"nav main aside";
}
}
The syntax
List one size per column, separated by spaces. The number of values is the number of columns. Items fill them left to right, and a new row starts when a row is full.
.layout {
display: grid;
grid-template-columns: 240px 2fr 1fr;
gap: 16px;
} grid-template-rows takes exactly the same values for rows. The difference is
that rows you do not declare are still created as content needs them, sized by
grid-auto-rows, so most grids declare their columns and leave rows alone.
Every value a column can take
| Value | What it does | Use it for |
|---|---|---|
| 240px / 15rem | Exactly that size, whatever the container does. | Sidebars, icon columns, anything with a fixed design size. |
| 25% | A share of the container width. Gaps are added on top, so 4 × 25% plus gaps overflows. | Rarely. fr does the same job without the gap maths. |
| 1fr | A share of the space left after fixed tracks and gaps. Will not shrink below its content. | Fluid columns. |
| minmax(0, 1fr) | A share of the leftover space that is allowed to shrink to zero. | Any fluid column holding images, code or long URLs. |
| auto | Sized to content, and stretches to fill leftover space when there is no fr track. | Columns that should fit their content, such as labels. |
| min-content | As narrow as possible: the width of the longest unbreakable word. | Tight label or button columns. |
| max-content | As wide as the content with no wrapping at all. | Short content that must stay on one line. |
| fit-content(300px) | Sized to content, but never wider than 300px. | Content-sized columns with a ceiling. |
| minmax(200px, 1fr) | Never narrower than 200px, otherwise fluid. | Responsive card grids, with repeat(). |
How fr divides the space
fr is not a percentage of the container. The browser first takes out every
fixed track and every gap, then splits what is left in proportion to the fr values.
/* 1000px container, 16px gaps:
1000 - 240 - 2 × 16 = 728px left over
2fr → 485px, 1fr → 243px */
grid-template-columns: 240px 2fr 1fr;
One catch. 1fr is shorthand for minmax(auto, 1fr), and that
auto minimum means a column never shrinks below its content. One long URL or
wide image and the column pushes the grid wider than its container. Write
minmax(0, 1fr) wherever that could happen.
repeat(): write the pattern once
repeat(count, size) expands to the same track written count times. It
also takes a pattern of several tracks, and it can sit alongside other values in the same
list.
grid-template-columns: repeat(3, 1fr);
/* same as 1fr 1fr 1fr */
grid-template-columns: repeat(12, minmax(0, 1fr));
/* a 12-column grid that never overflows */
grid-template-columns: repeat(2, 120px 1fr);
/* 120px 1fr 120px 1fr — repeat takes a pattern */ auto-fill and auto-fit: responsive columns with no media queries
Swap the count for auto-fill or auto-fit and the browser works
out how many columns fit. With a minmax() size, the columns are never narrower
than the minimum and share whatever is left over.
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
gap: 16px;
}
The min(100%, 240px) is there for screens narrower than 240px, where a plain
240px minimum would overflow. The two keywords only differ when there are too few items to
fill a row. auto-fill keeps the empty columns, so a lone card stays card-sized.
auto-fit collapses them, so the lone card stretches the full width.
One rule catches everyone: the size inside an auto-repeat needs a definite minimum.
repeat(auto-fill, 1fr) is invalid, and the whole declaration is dropped.
Use auto-fill when the column count does not matter. When it does, such as exactly three columns on tablet and four on desktop, you need breakpoints. That is what the responsive grid generator writes for you.
Named lines
Square brackets name the lines between columns, and items can then be placed by name
instead of by number. A line pair called content-start and
content-end can be targeted as just content. This is the
technique behind the full-bleed layout.
.page {
display: grid;
grid-template-columns:
[full-start] minmax(16px, 1fr)
[content-start] minmax(0, 60rem)
[content-end] minmax(16px, 1fr)
[full-end];
}
.page > * { grid-column: content; }
.page > .wide { grid-column: full; } For whole regions rather than lines, grid-template-areas names the areas themselves and draws the layout as a map. The two work together: the columns set the sizes, the map says what goes where.
Common column recipes
240px 1fr: fixed sidebar, fluid content.minmax(180px, 240px) 1fr: sidebar that can give up a little width on small screens.1fr 1frorrepeat(2, 1fr): equal halves.2fr 1fr: content plus a narrower aside.200px 1fr 200px: the three-column Holy Grail.repeat(12, minmax(0, 1fr)): a Bootstrap-style 12-column grid in plain CSS.repeat(auto-fill, minmax(min(100%, 240px), 1fr)): a card grid that reflows by itself.
Every value here is also in the CSS Grid cheat sheet, grouped with the other grid properties.
Layouts that show these column patterns
Frequently asked questions
What does grid-template-columns do?
grid-template-columns defines how many columns a grid has and how wide each one is, with one value per column. grid-template-columns: 200px 1fr makes two columns: a fixed 200px one and one that takes the rest.What does grid-template-columns: repeat(3, 1fr) mean?
repeat(3, 1fr) is shorthand for 1fr 1fr 1fr, and repeat() also accepts a pattern, such as repeat(2, 100px 1fr).What does 2fr 1fr mean in CSS grid?
2fr 1fr splits the free space into three parts and gives two to the first column and one to the second, so the first is twice as wide. Free space is whatever is left after fixed-size tracks and gaps are taken out.What is the difference between auto-fill and auto-fit?
auto-fill keeps the empty columns when there are too few items to fill a row; auto-fit collapses them so the items stretch across the full width. They only look different when the items do not fill a row.Why is repeat(auto-fill, 1fr) not working?
auto-fill and auto-fit need a definite size to count how many columns fit, and 1fr has none. Give it a minimum: repeat(auto-fill, minmax(240px, 1fr)).How do I make grid columns responsive without media queries?
grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)). Columns are at least 240px wide, as many as fit, and the min(100%, …) keeps a single column from overflowing on screens narrower than 240px.Why does my 1fr column overflow?
1fr is really minmax(auto, 1fr), and the auto minimum stops the column shrinking below its content. A wide image or a long unbroken string forces it open. Use minmax(0, 1fr) instead.What is the difference between grid-template-columns and grid-auto-columns?
grid-template-columns sizes the columns you declare. grid-auto-columns sizes columns the browser creates on its own, when an item is placed beyond the declared ones or grid-auto-flow: column is set.