CSS grid is a two-dimensional layout system: you describe a set of columns and the items are placed into the resulting cells. The direction of control is the reverse of flexbox. Flexbox asks each item how big it wants to be and then distributes the leftovers; grid asks you what the tracks are and then fits the items into them. Because both axes are described at once, a header, a sidebar and a footer can share column lines and stay aligned with each other, which no single-axis system can guarantee.
This generator produces the track list and hands you the declaration:
.grid-container { display: grid; grid-template-columns: 1fr 2fr 1fr; gap: 12px; }
Three columns, the middle one twice the width of its neighbours, twelve pixels of gutter. Every child element placed into that container lands in the next free cell, filling row by row, because that is the default grid-auto-flow behaviour.
Look carefully at the output: there is no grid-template-rows, and the Rows control does not appear in the CSS at all. It only changes how many preview boxes are drawn, so you can see a two-or-three-deep arrangement. In the real declaration, rows are created implicitly as items overflow the columns, and implicit rows are sized auto — each one is as tall as its tallest item. If you want uniform row heights you add grid-template-rows: repeat(3, 200px) or grid-auto-rows: 200px by hand.
| Track | How it is sized | Typical use |
|---|---|---|
1fr | One share of the free space that remains after fixed tracks and gaps are subtracted. Two 1fr tracks are equal; 1fr 2fr is a one-to-two split. | Equal columns, and any time you want the layout to absorb the container's width. |
2fr | The same unit with a larger weight, so this track takes twice the share of its neighbour. | A sidebar that is half the width of the content column. |
auto | Content-driven but flexible: it starts from the content's own size and is allowed to absorb leftover space. Its minimum is the item's minimum content size, so it will not squash content below its narrowest usable width. | A column that should fit its content but share the slack. |
min-content | The narrowest the column can be without overflowing — effectively the longest unbreakable word or the widest fixed-size child. | Forcing aggressive wrapping in a text column. |
max-content | Wide enough to lay everything out on one line, never wrapping. | A label column beside a fluid content column, so labels never wrap. |
| pixels | A fixed track, 10 to 600 px here, unaffected by available space. | Icon bars, rails, and any column whose width is a design decision rather than a consequence. |
Each column is set independently, which is the real difference from flexbox: auto 1fr max-content is a single legal declaration, and there is no per-item equivalent in a flex row. Mixing a fixed pixel rail with a fluid 1fr region — grid-template-columns: 240px 1fr; — is the classic application-sidebar shell in one line.
fr is not a percentageThis distinction is worth the paragraph. A percentage track resolves against the container's content box and knows nothing about the gaps, so three 33.33% columns with a 12px gap overflow by 24px. An fr track is only handed the space that is left after fixed tracks and gutters have been taken out, so 1fr 1fr 1fr with a 12px gap fits exactly and always will. This generator cannot emit percentage tracks at all, which quietly prevents the most common grid overflow bug.
1fr has an automatic minimum, so it can still overflow. A fraction track will not shrink below its content's minimum size, so one long unbreakable string or an image with an intrinsic width pushes the track wider than its fair share and the whole grid overflows. The fix is minmax(0, 1fr), which removes the automatic minimum, and it is essential before you can truncate text with an ellipsis inside a grid cell. The generator writes plain 1fr, so this is a hand edit.auto. Rows created by overflow are sized to their content, so two rows can end up different heights unless you declare them.grid-column: span 2 on the child.max-content column takes whatever its widest child needs, so a long product name can push a layout wider than the viewport. Combine it with minmax() or reserve max-content for genuinely short content.auto tracks costs more layout work. Content-based sizing feeds back into the algorithm and can require several measure passes, which is measurably slower than fixed tracks in very large trees. Fractions and pixels are cheap.The useful test is whether the rows need to line up. If the layout has genuine columns — a page shell, a dashboard, a gallery where every card must be the same width, form fields arranged in a matrix — use grid, because the tracks are defined once and everything inside them agrees. If you are arranging a run of items along one line and letting content decide the sizes, use flexbox. They compose happily: grid for the page regions, a flex row for the toolbar inside a header cell.
You can, and grid-template-columns: repeat(3, 1fr) is a perfectly good alternative to a flex row. The reason to still prefer flexbox there is that a flex container distributes an unknown number of items naturally, while a grid track list is a fixed shape you have to keep in sync with your markup.
No. Presentational grid creates no table semantics, so a screen reader receives a flat sequence of cells with no relationship between a value and its column heading. Use a real table for tabular data and reserve grid for layout.
Change the track list in a media query, or use repeat(auto-fit, minmax(220px, 1fr)), which creates as many tracks as fit and no more. This tool writes one fixed track list, so the adaptive version is a hand edit.
No, unless you must support Internet Explorer. IE10 and IE11 shipped an older, incompatible grid syntax with -ms- prefixes and different property names, and current Chrome, Firefox, Safari and Edge all implement the standard unprefixed syntax.
Usually, because auto-placement follows source order. It stops matching the moment you place items explicitly or span cells, and tab order and screen-reader order always follow the markup rather than the rendered position, so keep the source order meaningful.