CSS Grid Template Builder

How to use 3 steps
  1. Choose the Column sizing and set Columns and Rows.
  2. Set the Min column width, Column gap and Row gap.
  3. Press Copy Grid CSS and paste it into your stylesheet.
Col 1
Col 2
Col 3
Col 4
Col 5
Col 6
Generated CSS Grid Code

How this tool works

CSS Grid defines a layout in two dimensions at once. grid-template-columns is the important declaration: it describes the tracks, and the repeat() function saves writing the same width out several times. The fr unit divides whatever space is left over after fixed sizes are accounted for, so three columns of 1fr each take a third of the container regardless of what is in them.

The responsive mode is the one worth understanding. repeat(auto-fit, minmax(220px, 1fr)) tells the browser to fit as many columns as it can while none drops below 220px, and to share the remainder equally. That is a grid which reflows from four columns to one as the screen narrows, without a single media query. Row and column gaps are set separately here, since they rarely want to be equal.

Choosing tracks that behave

  • auto-fit is the responsive one: it collapses empty tracks so the remaining columns expand to fill the row. Its sibling auto-fill keeps empty tracks, which leaves a gap where a column would have been.
  • The minimum in minmax() is what sets your breakpoints: the column count changes when the container can no longer fit another track at that width. Choosing it is choosing where the layout reflows.
  • 1fr is not the same as auto: fr divides leftover space equally whatever the content is; auto sizes each track to its contents, so columns end up uneven.
  • Rows are usually better left implicit: declaring a fixed number of rows means content beyond them lands in rows you did not describe. Setting columns and letting rows create themselves is the more forgiving arrangement.

The one line worth learning

Most of what makes CSS Grid useful for page layout sits in a single declaration:

grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));

That tells the browser to fit as many columns as it can while none drops below 220 pixels, and to share whatever is left over equally between them. The result reflows from four columns to three to one as the screen narrows, without a media query anywhere. A card list, a product grid, a set of team photos — all of them stop needing breakpoints.

The [msm_tool slug="grid-generator"] writes that line along with the simpler equal-column and content-sized variants, but the value is in understanding what the minimum does, because that number is where your layout reflows.

fr is not a unit of size

The fr unit divides the space that is left after everything else has been accounted for — fixed track widths, gaps, content that refuses to shrink. Three columns of 1fr take one third of the remainder each, whatever is inside them.

That is different from auto, which sizes each track to its own contents and produces uneven columns. It is also different from a percentage, which is a fraction of the container and does not account for the gaps — three columns of 33.33% plus two gaps overflows, and 1fr does not.

auto-fit and auto-fill

These look interchangeable and behave differently in exactly one situation: when there are fewer items than tracks.

auto-fit collapses the empty tracks, so the items you do have stretch to fill the row. auto-fill keeps them, leaving space where a column would have been.

Neither is correct in general. If a two-item row should stretch across the full width, use auto-fit. If those two items should stay the width they would have been in a full row — which is usually what you want when the grid fills up over time — use auto-fill.

Choosing the minimum

The minimum in minmax() is your breakpoint, expressed as a property of the content rather than of the device. The column count changes when the container can no longer fit another track at that width.

Pick it from what has to fit inside. A card with a heading and two lines of description needs perhaps 220 to 280 pixels before it starts looking cramped; a photo tile can go much smaller; a data table cannot. Choosing 300 because it produces three columns on your laptop is choosing a breakpoint by accident.

One trap worth knowing: a fixed minimum can overflow a narrow container, because minmax(220px, 1fr) means the track will not go below 220 pixels even if there is not 220 pixels available. On a 200-pixel container it overflows. minmax(min(220px, 100%), 1fr) is the defensive form.

Rows are usually better left alone

Declaring a fixed number of rows means content beyond them lands in rows you never described, sized by whatever the implicit row rule happens to be. Setting columns and letting rows create themselves is the more forgiving arrangement, and it is what nearly every card grid wants.

Declare rows when the layout genuinely is two-dimensional and known in advance — a dashboard with a header, sidebar and content area, for instance, where you know exactly how many rows there are and what each should do.

Gaps

Row and column gaps are set separately here because they rarely want to be equal. Vertical space between cards usually needs to be larger than horizontal space to read as deliberate grouping, and a single gap value forces them together.

Gaps are also the reason grid replaced margin-based spacing. There is no leading or trailing gap to strip off, no first-child or last-child rule, and no negative margin on the container to compensate.

Grid or flexbox

The distinction that holds up in practice: use grid when the layout is defined before the content, and flexbox when the content decides the sizes.

A gallery of equal cards is a grid — you know the shape and the items fill it. A row of buttons whose widths depend on their labels is flexbox. A page skeleton with a header, sidebar and footer is a grid. A navigation bar with a logo on the left and links on the right is flexbox.

They also nest happily, and most real pages use both. A grid for the page, flexbox inside each card.

What to check before shipping

  1. One item. Does a single card stretch across the entire row, and should it? This is where auto-fit versus auto-fill shows up.
  2. An awkward count. Five items in a grid that fits four leaves one alone on the second row. That is fine, but it should look intentional.
  3. Long content. A card with a heading four times longer than the others sets the row height for all of them, since rows size to their tallest item.
  4. A narrow container. Not just a narrow screen — a grid inside a sidebar has far less room than the same grid in a main column.

Frequently Asked Questions

Specific to the CSS Grid Template Builder. Broader questions about this category are answered on the category page.

One share of the space left after fixed-width tracks and gaps are subtracted. Three columns of 1fr each take one third of what remains.
Use the responsive sizing mode. repeat(auto-fit, minmax(220px, 1fr)) fits as many columns as will hold that minimum and reflows on its own.
auto-fit collapses empty tracks so the visible columns stretch to fill the row. auto-fill keeps them, leaving empty space where a column would be.
The sizing mode is set to auto, which sizes each track to its contents. Equal columns need fr units.
Rarely. Declare columns and let rows be created as content arrives — a fixed row count means anything beyond it lands in tracks you never described.

Subscribe to receive notifications about new tools, features, and productivity tips.