cssgridgenerator All tools
Property guide

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.

Open in
1204px

Drag across the grid to draw an area. Arrow keys nudge, Shift + arrows resize.

space to pan · ⌘scroll to zoom
1240px22fr31fr4
1auto2
nav1 / 1 / 2 / 2
main1 / 2 / 2 / 3
aside1 / 3 / 2 / 4

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 1fr or repeat(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

Browse all layout 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?
It makes three equal columns that share the available width. 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?
Both fit as many columns as the container allows. 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?
Because 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?
Use 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.