CSS Grid Generator
Design CSS grid layouts visually and copy the CSS
Cells are numbered in reading order; gaps update live as you drag.
Named areas replace the column/row sliders with a preset region layout.
CSS Grid is the two-dimensional layout system in modern CSS: you describe rows and columns at once and let the browser place items into that structure. This generator gives you sliders for tracks and gaps, a live preview, three named-area presets, and clean CSS you can copy straight into a stylesheet. It is aimed at the first 80 percent of a grid — equal columns, even gaps, and a simple region diagram — so you can start a layout in seconds instead of hand-typing template strings.
How to Use
- Drag the columns and rows sliders (1–12 each) or type a number in the box beside each one. The preview redraws on every change.
- Set column-gap and row-gap independently, from 0 to 48 pixels. Because they are separate properties, you can use tight column gutters and generous row spacing.
- Optionally tick named areas and choose a preset — Holy Grail, Sidebar, or Cards. The sliders lock to the preset’s dimensions.
- Copy the
.containerblock. With named areas on, also copy the.area-namerules the generator appends.
Worked Examples
Example A — a four-by-two card grid. Columns 4, rows 2, column-gap 16, row-gap 12 produces:
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);
column-gap: 16px;
row-gap: 12px;
}
Example B — the Holy Grail preset. Enabling named areas and selecting Holy Grail switches the track count to 3 x 3 and appends a diagram:
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
The generator then emits one rule per region, such as .header { grid-area: header; }. Any direct child you give that class is placed automatically, and main stretches across the single middle cell while the header and footer span all three columns.
Reading the Generated CSS
Three declarations carry most of the meaning. display: grid turns the element into a grid container. grid-template-columns and grid-template-rows define the tracks; repeat(n, 1fr) means n equal fractions of the leftover space. The fr unit does not mean “one nth of the container” in a naive sense — gaps are subtracted first, then the remainder is split. For a 1200px container with three columns and 16px column gaps, the gaps consume 32px and each 1fr resolves to (1200 - 32) ÷ 3 ≈ 389.3px. grid-template-areas is a visual map: repeated names merge cells into one region, and a dot leaves a cell empty.
Tracks vs Named Areas: Which to Use
| Situation | Better choice | Why |
|---|---|---|
| Uniform card gallery, item count unknown | Plain tracks | Track count is the only decision; items wrap naturally when you add media queries |
| Page skeleton with header/sidebar/footer | Named areas | The diagram documents the layout and survives reordering |
| One feature block spanning two columns and two rows | Named areas | Repeating a name merges cells, which is hard to express with equal 1fr tracks alone |
| You need mixed fixed and flexible widths | Start with tracks, then edit | The generator only emits 1fr; replace individual tracks by hand |
Common Mistakes
- Assuming gaps shrink the tracks automatically. They do, but only if your grid items can shrink. A min-width on a card can force a track wider than
1frand cause horizontal overflow across 10–12 columns; swap inminmax(0, 1fr)when that happens. - Styling grandchildren. Grid placement applies to direct children only. A wrapper
<div>between the container and the cards breaks the intended layout. - Renaming an area in the diagram but not the class. The
.headerrule and the"header header header"string must match exactly; a typo silently leaves an item unplaced. - Forgetting that named areas reorder without moving HTML. Visual order and source order diverge, which matters for keyboard tab order and screen readers — check accessibility if the visual order changes meaning.
- Expecting the preview to be responsive. The demo grid is fixed; real responsiveness still needs
@mediarules orauto-fit/minmax, which this generator does not produce.
Accuracy and Limits
The output uses standard, widely supported grid properties, and zero gaps are omitted so the CSS stays lean. What you will not get: auto-fit, auto-fill, minmax(), subgrid, per-item span controls, or generated media queries. Track counts always resolve to equal fractions, and gaps cap at 48px. Treat the result as a correct, readable starting point rather than a finished responsive layout.
Responsive Behavior You Still Need to Add
The generator emits a fixed track count, not a container query. A four-column desktop grid will squeeze cards uncomfortably at 375px unless you add breakpoints yourself. A common pattern is to keep the generated block as the desktop base and layer progressively simpler grids below it:
@media (max-width: 900px) {
.container { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
.container { grid-template-columns: 1fr; }
}
An alternative that needs no media queries is grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)), which fits as many 220px-minimum columns as the container allows and wraps the rest. It is more resilient to unknown item counts, but the tool does not generate it. For a card gallery fed by a CMS, prefer the auto-fit form; for a page skeleton with named regions, keep the explicit tracks and add one breakpoint that stacks the regions into a single column.
Related Tools
- CSS Flexbox Generator — Design one-dimensional flexbox layouts with live preview.
- CSS Box Shadow Generator — Design layered box shadows with live preview.
- CSS Gradient Generator — Build custom CSS gradients for your layouts.
Frequently Asked Questions
Why does the generated CSS use repeat(3, 1fr) instead of writing 1fr 1fr 1fr?
repeat() is a compact shorthand: repeat(3, 1fr) expands to 1fr 1fr 1fr, and repeat(12, 1fr) expands to twelve copies without a long line. Both are identical to the browser, but the shorthand stays readable when you change the track count and makes it obvious that every track is equal.
If I enable named areas, why do the column and row sliders stop working?
A grid-template-areas matrix already defines the shape. The Holy Grail preset, for example, is three columns by three rows, so the generator derives the track count from the preset and disables the sliders to avoid contradicting the diagram. Turn named areas off to regain manual track control.
Can I mix fixed pixel columns with fr units in the output?
Not through the sliders. Every track the tool emits is an equal 1fr. To build a layout with, say, a 240px sidebar and a flexible main column, copy the generated CSS and replace the relevant track, for example grid-template-columns: 240px 1fr. The generator gives you the skeleton; the hand edit gives you the proportions.
What are the largest grid and gap values the generator supports?
Columns and rows each range from 1 to 12 tracks, and both column-gap and row-gap range from 0 to 48 pixels. Typing a number outside those bounds is clamped to the nearest valid value.
Why are zero gaps left out of the CSS?
The default grid has no gaps at all, so writing column-gap: 0 adds noise. The generator omits any gap declaration that is zero and only emits the property once you raise the slider above 0, keeping the copied block minimal.
Do I need to quote every row inside grid-template-areas?
Yes. Each row of the diagram is a separate quoted string with one cell per column, separated by spaces, and every row must contain the same number of cells. A period marks an empty cell. The generator writes these strings for you, so the only thing you have to keep in sync is the matching .area-name rule.
Reviewed by the HandyTools Hub team · Last updated