cssgridgenerator

CSS Grid Visualizer

Paste CSS. See the grid. Change it, and take the code back.

Free tool

The only grid tool that reads CSS as well as writes it

Every other grid generator is write-only. You draw a layout, copy the code, and the moment that layout lives in a stylesheet the tool has nothing left to offer — the next change is back to counting line numbers in your head. This reads the CSS back, which makes the same editor a debugger for grids you did not write.

How to use it

  1. Paste the CSS

    Drop in the rule that has display: grid on it, along with the child rules and any media queries. A whole stylesheet is fine — everything that is not part of the grid is ignored.

  2. Read the layout

    The grid is drawn as areas on a canvas, one view per breakpoint. Drag the width ruler to see what the layout does at each media query.

  3. Change it

    Move an area, resize a track, add a breakpoint. It is the same editor as the generator, so everything works the same way.

  4. Take it back

    Copy the CSS out, or the HTML, Tailwind, React, Vue or Svelte version of it. The media queries are rewritten to contain only what actually differs.

What it reads

The container rule — display: grid, the track lists, the gaps — and the two ways of placing children: a grid-template-areas map, or child rules using grid-area, grid-column and grid-row. Both forms are understood, including span counts and negative line numbers like 1 / -1. A child with display: none is read as "not rendered at this width", which is exactly what it means.

Every @media (min-width: …) block becomes a breakpoint, in ascending order, and the values cascade the way the browser cascades them: a query that only changes the columns inherits everything else from the width below it. min-width in em and the modern (width >= 900px) range syntax both work.

What it cannot do, and says so

It is a layout reader, not a CSS engine. It does not resolve custom properties, follow imports or arbitrate specificity between two rules that fight over the same element. And repeat(auto-fill, …) has no fixed column count by definition — the number depends on the container at render time — so the editor shows a workable number of tracks and tells you it did. Anything skipped is reported above the canvas rather than dropped quietly, because a visualiser that silently loses half your layout is worse than one that refuses it.

Using it to debug

Two failures account for most broken grids, and both are visible the moment the layout is drawn. The first is an area map whose rows have different lengths: that makes the whole grid-template-areas declaration invalid, so the browser throws it away and the layout falls back to auto-placement. The importer flags it instead of guessing.

The second is an item placed outside the tracks that exist — grid-column: 1 / 5 in a three-column grid. The browser creates implicit tracks to hold it, which is why the layout looks right in one place and collapses in another. On the canvas the item is simply past the edge of the defined grid, which takes about a second to spot.

It goes both ways

What comes out is not what went in — it is the same layout, re-emitted. Media queries carry only the properties that actually change at that width, item placements that are unchanged are not repeated, and the output is available as Tailwind, a React, Vue or Svelte component, or a shadcn-style compound component. Pasting a grid in and taking a tidier one out is a reasonable way to use this on its own.

If you would rather start from a layout than from code, the grid generator begins with a blank canvas and the layout pattern library has 46 of them ready to edit.

Frequently asked questions

How do I visualise CSS Grid code?
Paste the rule that carries display: grid, together with its child rules and any media queries. The layout is drawn as areas on a canvas, one view per breakpoint, and you can drag the width ruler to see what happens at each media query.
Does it read grid-template-areas or line numbers?
Both. An area map is read as named regions; child rules using grid-area, grid-column and grid-row are read as line placements, including span counts and negative lines such as 1 / -1. A child with display: none is treated as not rendered at that width, which is what it means.
Why does my grid look wrong in the browser but fine in the code?
Two causes account for most of it. Rows of different lengths in grid-template-areas make the whole declaration invalid, so the browser discards it and falls back to auto-placement. Or an item is placed outside the tracks that exist — grid-column: 1 / 5 in a three-column grid — and the browser creates implicit tracks to hold it. Both are obvious once the layout is drawn.
What happens to repeat(auto-fill, …)?
It cannot be drawn exactly, because the column count depends on the container width at render time rather than on anything in the CSS. The editor expands it to a workable number of tracks and says so above the canvas — put the repeat() back when you copy the CSS out.
Is the CSS I paste sent anywhere?
No. The parser runs in your browser, there is no account and nothing is uploaded. The layout is encoded into the address bar as you work, which is also how a shareable link is made.
Can I get the layout back out as a component?
Yes — CSS, HTML, Tailwind, a React, Vue or Svelte component, or a shadcn-style compound component. The re-emitted CSS is diffed, so each media query contains only the properties that actually change at that width.