The tool you need, ready to use

CSS Grid Generator

The box on the stage is a real CSS Grid. Drag across empty cells to draw an area, drag an area to move it, or pull its corner to stretch it. Click a chip on the top or left ruler to change a track to something like 1fr, 200px or minmax(120px, 1fr). Under the stage, a formula shows how many px 1fr is right now and how many auto columns fit. Copy the finished layout as CSS and HTML, using grid-template-areas or line numbers.

Last updated 2026-10-22All math stays in your browser
Cols
Rows
With an area focused, the arrow keys move it one cell at a time, and Shift with the arrow keys extends or shrinks its right and bottom edge. The Delete key removes the area. The Left and Right arrow keys change the width and the Up and Down arrow keys change the height by 10px. Hold Shift for 50px steps, and press Home to fit the width to the stage.

Grid.grid
Columns grid-template-columns
px
px
px
px
Fill gaps (dense) grid-auto-flow
Justify items justify-items
Align items align-items
Area
Count
Selected area
Placement

Arrow keys move · Shift+arrows resize


  

Last updated 2026-10-22Your inputs are not stored

ROBERIN standardThe tool you need,
ready to use.
  • Clear at a glanceInputs and results sit where you expect them.
  • Result firstThe key number comes first; the working only when you need it.
  • Ask lessNo sign-up and no unnecessary details.

A CSS Grid generator: draw areas by dragging cells

The box on the stage of this CSS Grid generator is a real display: grid container. The rulers above and to the left show each column and row track with the value you wrote, the px size the browser computed, and the line numbers. Drag across empty cells to create an area that covers that range, drag an area to move it cell by cell, and drag the bottom-right corner of the selected area to extend or shrink it. Click a chip on a ruler to change that track to something like 1fr, 200px or minmax(120px, 1fr).

The sentence under the stage walks through how big 1fr is right now, in calculation order, and for auto-generated columns it shows how many columns fit as a formula. Copy the finished layout as CSS that uses grid-template-areas with area names or with line numbers, or take the HTML along with it. Copy link stores the current layout in the address.

When Grid fits: aligning rows and columns together

CSS Grid is a two-dimensional layout: you define the column and row boundaries first, then place items into those cells. Because the tracks, not the item content, decide the cell sizes, the edges line up exactly from one row to the next. It is especially useful in screens like these.

  • Page skeleton: split fixed regions such as header, sidebar, main content and footer. With area names, the CSS alone shows the layout (examples "Basic page" and "Holy Grail").
  • Dashboard: place several small metric cells and a large chart that spans two or more cells in the same grid (example "Dashboard").
  • Card lists: keep every card the same width on every row even as the column count changes with the screen width. When you wrap a row in Flexbox, the cards on the last row tend to stretch; Grid cards follow the track width, so they don't (example "Auto-fit cards").
  • Photo collections with mixed sizes: mix photos that span two or four cells and fill the holes with dense (example "Photo mosaic").
  • Layering: give two areas the same cells and you can put text over an image without any position math. Drag an area over another one on the stage to see the overlap.

For a menu or a button group that is laid out in one direction and shares space only within that line, Flexbox is simpler.

How to use it

  1. Pick an example. Click one of the 9 tiles at the top and the tracks, gaps and areas all change at once. Areas that change slide from their old position to the new one.
  2. Set the tracks. Add or remove tracks with the column and row buttons in the top row, and click a ruler chip to change a size. In the panel on the right you can type a value or choose a common one, and insert a track before or after the selected one.
  3. Draw the areas. Drag across empty cells to create an area, drag an area to move it, and drag its bottom-right corner to resize it. With the keyboard, focus an area and use the arrow keys to move it one cell, Shift with the arrow keys to extend or shrink it, and Delete to remove it. Rename an area in the panel.
  4. Check the widths. Change the container width with the Full, 768, 480 and 360 buttons in the top row or the handle at the bottom right of the stage, and you immediately see how the fr tracks shrink and how many auto columns remain.
  5. Copy. Choose area names or line numbers, then click Copy CSS or Copy HTML + CSS. Turn on Include preview styling to add borders and backgrounds, so the cells are visible even when you paste into an empty file.

How to read track values

grid-template-columns and grid-template-rows take one size per track. When the same value repeats you can shorten it to something like repeat(3, 1fr), and this tool writes it that way when all tracks are equal.

ValueHow the size is decidedUse it when
200pxFixed, regardless of the container widthSidebars, icon cells
25%A share of the container's inner width; gaps are added on topYou need an exact proportion (tracks totaling 100% plus gaps overflow)
1frA share of the space left after other tracks and gapsYou want to fill all the remaining space
autoContent size; stretches into the leftover space when there is no fr trackHeader and footer rows whose height should follow the content
min-contentThe narrowest width the content can take (the longest word)A cell that should stay as narrow as possible, like a label
max-contentThe width of the content on one line, without wrappingShort items that must not wrap
minmax(120px, 1fr)From a minimum of 120px up to a maximum of 1frA cell that must not get too narrow
minmax(0, 1fr)From a minimum of 0 up to a maximum of 1frSplitting column widths evenly even when a long word is present
fit-content(240px)Follows the content size but never exceeds 240pxNarrow when the content is short, up to the cap when it is long

How many px is 1fr: the order for sharing leftover space

An fr is not a fixed length but a factor for dividing the leftover space. The browser decides the size of 1fr in this order.

  1. Subtract the gaps (number of tracks − 1) and the sizes of the non-fr tracks from the inner width. What remains is the leftover space.
  2. Divide the leftover space by the sum of the fr factors to get the size of 1fr. If the factors add up to less than 1, you divide by 1 instead, so part of the leftover space stays empty.
  3. Any fr track whose minimum size is larger than its share is fixed at that minimum, and the remaining fr tracks share what is left again. The minimum size of 1fr is auto, so the width of a long word or an image in the cell becomes the minimum.

The table below shows the column widths that Chromium 151 computes for a container with an inner width of 800px and a column gap of 16px (only the last row uses an inner width of 600px and no gap). Enter the same values on the stage and the sentence below it shows the same formula.

grid-template-columnsLeftover space1frColumn widths
1fr 1fr 1fr768px256px256 · 256 · 256
200px 1fr584px584px200 · 584
1fr 2fr 1fr768px192px192 · 384 · 192
240px 1fr 2fr528px176px240 · 176 · 352
25% 1fr584px584px200 · 584
0.5fr 0.25fr784px784px (factors total 0.75 → divided by 1)392 · 196 (196px left empty)
minmax(240px, 1fr) 1fr 1fr600px → 360px180px240 · 180 · 180

In the last row, the browser first divides 600 ÷ 3 = 200px, but the first column's minimum of 240px is larger than the 200px share, so that column is fixed at 240px. The remaining 360px is split between the other two columns at 180px each. A 2fr column is exactly twice a 1fr column only when both shares are larger than their minimum sizes.

Area names and line numbers

A grid with n columns has vertical lines numbered 1 through n + 1. The small numbers on the stage rulers are these line numbers. grid-column: 1 / 3 runs from line 1 to line 3, so it covers two columns, and grid-row: 2 / 4 covers two rows. The last line can also be written as -1, so 1 / -1 is the full width whatever the column count.

grid-template-areas takes one pair of quotes per row and one area name per cell. An empty cell is a period (.). Written with area names, the "Basic page" example looks like this.

.grid {
  display: grid;
  grid-template-columns: 180px 1fr;
  grid-template-rows: 56px 1fr 48px;
  grid-template-areas:
    "header header"
    "side   main"
    "footer footer";
  gap: 12px;
}
.header { grid-area: header; }
.side { grid-area: side; }

The cells that share a name must form a single rectangle. If they are L-shaped or separated, the whole declaration is invalid. The items given grid-area: name then can't find their area, and they all stack in the same cell created outside the explicit grid. Every string must also have the same number of cells. A layout where two areas share the same cells can't be written with names, so when an overlap appears this tool switches to line numbers and tells you why above the code.

Area names let you picture the layout from the CSS alone, and you can redo the layout per screen width by changing only the strings in a media query. Line numbers are shorter when there are many cells, as in a 12-column grid, or when areas must overlap.

auto-fit and auto-fill: letting the width decide the column count

Choose "Auto by width" and the column definition takes the form repeat(auto-fill, minmax(min(100%, 160px), 1fr)). The browser creates as many columns as fit without overflowing, and the count is ⌊(inner width + gap) ÷ (min width + gap)⌋. min(100%, 160px) lowers the minimum width to the parent's width when the parent is narrower than 160px, so a single column doesn't spill out sideways.

auto-fit and auto-fill look different only when there are fewer areas than columns. auto-fill keeps the empty columns as space, while auto-fit collapses empty columns to 0 along with the gaps on either side, so the remaining areas grow wider. With a 160px minimum, a 16px gap and 3 areas, the result is as follows.

Inner widthColumnsauto-fill cell widthauto-fit cell width
360px2172px172px
600px3189.3px189.3px
800px4188px256px
1000px5187.2px322.7px

At 360px there are 2 columns, so the third area drops to the next row, and at 600px the area count equals the column count, so both methods match. Choose auto-fill if you don't want a card or two to grow too wide, and auto-fit if you want the cards you have to fill the width.

Beyond the explicit grid: implicit rows and dense

When there are more areas than the rows set with grid-template-rows, the browser adds more rows. These are called implicit rows, and grid-auto-rows sets their size (default auto). On the stage, the chips and cells of implicit tracks are drawn with dotted lines. Card lists often define no rows at all and set only grid-auto-rows.

An area with no position looks for a free cell in HTML order. If a two-cell area doesn't fit at the end of a row, it moves to the next row and leaves a hole before it. With grid-auto-flow: dense, a later, smaller area fills the earlier hole. In the "Photo mosaic" example, turning Fill gaps off leaves row 1, column 4 empty, and turning it on moves p5 up into that spot. Note that dense changes only the visual order; Tab key order and screen reader order stay in HTML order.

Alignment inside a cell

By default an area fills its cell with stretch. justify-items sets the horizontal position inside the cell and align-items the vertical position; with start, center or end, the area shrinks to its content size and sits there. Setting both to center is the same as the single line place-items: center, and the "Centered" example shows that layout. To align just one area, give it justify-self and align-self.

When the tracks add up to less than the container, the whole set of tracks sticks to the start side (top left). This is the case the sentence under the stage describes as "the right side is empty"; to move the set to the middle, add justify-content: center to the container.

Browser support

Below are the first supported versions listed in MDN's browser compatibility data. The code this tool generates does not use subgrid.

FeatureChromeFirefoxSafari
display: grid, grid-template-columns575210.1
grid-template-areas575210.1
gap (grid)666112
min() function797511.1
subgrid (for reference)1177116

Common mistakes

  • The 1fr columns have different widths. A cell holds a long URL or a large image whose minimum size is larger than its share. Switch to minmax(0, 1fr) and wrap the overflowing text separately.
  • Four 25% tracks overflow. Gaps are not included in % tracks. With a 16px gap, 48px overflows, so use repeat(4, 1fr).
  • A 1fr row doesn't grow. If the container height is auto, there is no leftover height to share. Give it a height, such as height or min-height: 100dvh.
  • The whole grid-template-areas is ignored. Either the strings have different numbers of cells, or a name doesn't form a rectangle.
  • Cards overflow sideways on narrow screens. minmax(240px, 1fr) holds 240px even when the parent is narrower. Change it to minmax(min(100%, 240px), 1fr).
  • An extra column appears and causes horizontal scrolling. A span larger than the column count creates an implicit column. It happens most often in auto columns at narrow widths, so check with the 360px button.
  • The reading order is off after filling with dense. Only the visual order changed. For a list where order matters, turn dense off or fix the HTML order.

Limits and cautions

  • The stage shows only the left-to-right horizontal writing direction.
  • The areas on the stage contain only their name, and they have min-width: 0 and overflow: hidden so that the text doesn't widen the tracks. The default code holds layout properties only and leaves these two lines out, so even the same name can widen a 1fr column, whose minimum is auto, to the width of the text. Turn on 'Include preview styling' to add these two lines with the stage's padding, border and font size, and the code draws at the same size as the stage. With real content, auto, min-content and fr tracks will size differently from the stage.
  • You can create up to 12 explicit tracks each for columns and rows, and up to 24 areas. Named lines, negative line numbers, subgrid, grid-auto-columns, justify-content and align-content, per-area justify-self and align-self, and media queries are not put in the code.
  • The value in the Height field is the content height without padding. The height in the code is written with the same meaning (content-box).
  • The 768, 480 and 360 buttons change the container width. This differs from a media query, which is based on the screen (viewport) width.
  • The fr explanation recalculates from the track sizes the browser drew. If they differ by more than 0.6px, it tells you the formula is approximate.
  • Copy link stores the area names in the address too.

As of The W3C CSS Grid Layout Module Level 2 (Candidate Recommendation Draft 2025-03-26) and the MDN browser compatibility data were checked against the originals on 2026-10-21. The column widths in the tables were measured on a real grid container in Chromium 151.

Sources

  • 01W3C: CSS Grid Layout Module Level 2Candidate Recommendation Draft 2025-03-26. §6.6 automatic minimum size of grid items, §7.2.1 track sizes (fr outside minmax() has a minimum of auto), §7.2.3.2 auto-fill and auto-fit repetition count and collapsing empty tracks, §7.3 grid-template-areas (the declaration is invalid unless the areas are rectangles), §7.5 the implicit grid and grid-auto-rows, §7.7 dense in grid-auto-flow, §11.1 gutters (gaps of collapsed tracks), §12.7.1 finding the size of an fr (factors summing to less than 1, recalculating after excluding tracks with a larger minimum)
  • 02MDN: grid-template-columnsTrack value syntax and browser compatibility table: Chrome 57, Firefox 52, Safari 10.1; subgrid Chrome 117, Firefox 71, Safari 16
  • 03MDN: grid-template-areasArea name syntax and browser compatibility table: Chrome 57, Firefox 52, Safari 10.1
  • 04MDN: gapBrowser compatibility table: in grid layout, Chrome 66, Firefox 61, Safari 12
  • 05MDN: min()Browser compatibility table: Chrome 79, Firefox 75, Safari 11.1

Frequently asked questions

How do I make 3 equal-width columns with CSS Grid?

Give the container display: grid and grid-template-columns: repeat(3, 1fr). With an inner width of 800px and a column gap of 16px, the 768px left after the 32px of gaps is split three ways, so each column is 256px. To keep the widths identical even when a cell holds a long URL or an image, write repeat(3, minmax(0, 1fr)).

What is the difference between fr and %?

A % is a share of the container's inner width, so gaps are added on top, while fr divides the space left after other tracks and gaps are subtracted. With a 16px gap, four 25% tracks overflow by 48px, but four 1fr tracks do not.

What is the difference between auto-fit and auto-fill?

Both create as many columns as fit without overflowing, but when there are fewer areas than columns, auto-fill keeps the empty columns as space and auto-fit collapses them to 0 so the remaining areas grow wider. With an inner width of 800px, a 160px minimum, a 16px gap and 3 areas, auto-fill gives 188px and auto-fit gives 256px.

I wrote grid-template-areas but it isn't applied. Why?

Check that every string has the same number of cells and that the cells sharing a name form a single rectangle. If either rule is broken, the whole declaration is invalid. Each item also needs its own grid-area: name, and the names are written without quotes.

How do I make the column count change with the screen width?

Write something like grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)) and the column count follows the width without a media query. The count is (inner width + gap) ÷ (min width + gap), rounded down. In this tool, choose "Auto by width" and change the width with the handle to see where the columns change.

How do I center an item inside a Grid?

Give the container place-items: center, or set both justify-items and align-items to center. To center vertically, the cell needs spare height, so set the height of the row or the container as well. Click the "Centered" example to see it at once.

Why doesn't my 1fr row grow?

If the container height is auto, there is no leftover height to share, so the fr row grows only to its content height. Set a container height, such as height or min-height: 100dvh, and the 1fr row takes the leftover height.

Should I use Grid or Flexbox?

Grid suits page skeletons, dashboards and card lists, where row and column edges must line up together; Flexbox suits menus and button groups that line up in one direction and share space within that line. The two are often combined: use Grid to divide the regions and Flexbox to align the row of buttons inside each region.