CSS grid

On this page 7

CSS Grid (formally the CSS Grid Layout Module) is a two-dimensional layout system in CSS that divides a container into rows and columns and places child elements into the resulting cells or areas. Unlike older techniques built on floats or inline blocks, it lets the author define the layout structure on the parent and then position items independently of their order in the HTML source.

In web development, CSS Grid is the standard tool for page-level layouts, card galleries, dashboards and any design in which content must align along both axes at once. It is supported by all current major browsers, and it complements Flexbox, which distributes items along a single axis.

How CSS Grid builds a layout

CSS Grid works by turning an element into a grid container with display: grid, after which its direct children become grid items. The author then defines tracks (rows and columns) with grid-template-columns and grid-template-rows, and the browser computes the size of every track before placing items onto the grid.

The space between two adjacent grid lines is a track; the intersection of one row track and one column track is a grid cell; any rectangle of cells is a grid area. Lines are numbered from 1 at the start edge and from -1 at the end edge, so grid-column: 1 / -1 makes an item span the full width regardless of how many columns exist.

The table below summarizes the core vocabulary that every grid declaration relies on.

ConceptWhat it isTypical property
Grid containerElement that establishes the grid formatting contextdisplay: grid or inline-grid
Grid trackOne row or one column of the gridgrid-template-columns, grid-template-rows
Grid lineNumbered or named boundary between tracksgrid-column-start, grid-row-end
Grid areaRectangle spanning one or more cellsgrid-template-areas, grid-area
GapFixed gutter between tracksgap, row-gap, column-gap
Implicit trackTrack created automatically for overflow itemsgrid-auto-rows, grid-auto-flow
Core building blocks of a grid

When items outnumber the explicitly defined cells, the auto-placement algorithm creates implicit tracks sized by grid-auto-rows or grid-auto-columns. Setting grid-auto-flow: dense lets the algorithm backfill earlier holes, which produces a compact layout but can break the visual reading order.

Track sizing and the fr unit

Track sizing is where CSS Grid differs most from earlier layout methods, because it introduces the fr unit, which represents a fraction of the remaining free space after fixed and content-based tracks have been sized. A declaration such as grid-template-columns: 240px 1fr 2fr gives the first column a fixed width and splits the rest in a one-to-two ratio.

Several sizing functions combine with fr to create layouts that adapt without media queries. The most widely used values are compared below.

ValueBehaviorTypical use
frShares remaining free space proportionallyFlexible main columns
minmax(min, max)Clamps a track between two sizesColumns that must not shrink below a readable width
autoSizes to content, then stretches if space remainsHeader or footer rows
min-content / max-contentSizes to the smallest or largest content widthLabels and sidebars that fit their text
fit-content(limit)Grows with content up to a limitNavigation columns with a cap
repeat(auto-fit, ...)Creates as many tracks as fit, collapsing empty onesResponsive card grids
Track sizing values and their behavior

The pattern repeat(auto-fill, minmax(16rem, 1fr)) is the canonical responsive grid without breakpoints: the browser fits as many 16rem columns as the container allows and stretches them evenly. The difference between auto-fill and auto-fit appears only when items do not fill a row: auto-fill keeps empty tracks, while auto-fit collapses them so existing items expand.

A frequent surprise is that 1fr has an implicit minimum of auto, so a long word or a wide image can force the track wider than its share. Writing minmax(0, 1fr) removes that minimum and prevents unexpected overflow.

CSS Grid compared with Flexbox and older methods

CSS Grid and Flexbox solve different problems: Grid is layout-first, defining the structure before content arrives, while Flexbox is content-first, letting item sizes drive distribution along one axis. Most production interfaces combine both, typically Grid for the page skeleton and Flexbox for components such as toolbars or button rows.

TechniqueDimensionsStrengthMain limitation
CSS GridTwo (rows and columns)Precise alignment on both axesMore verbose for simple one-line rows
FlexboxOne (row or column)Content-driven distribution and wrappingWrapped lines do not align with each other
FloatsNone by designText wrapping around imagesRequires clearing hacks for layout
Table layoutTwoNative alignment of cellsTies presentation to tabular markup
Grid, Flexbox and legacy layout techniques

The subgrid value, defined in CSS Grid Layout Level 2 and now supported by all major engines, lets a nested grid inherit the parent’s tracks. It solves the classic problem of card components whose titles, images and buttons must line up across siblings. Grid also pairs well with container queries, which adapt a grid to the width of its component rather than the viewport.

Named areas and placement in practice

The grid-template-areas property lets an author draw the layout as text, assigning a name to each cell so that items are placed with a single grid-area declaration. This makes the structure readable at a glance and allows a complete layout change inside one media query by redefining only the area map.

Choosing the right placement method depends on how stable the structure is and who maintains it, as the decision table shows.

SituationRecommended methodReason
Fixed page skeletonNamed template areasSelf-documenting and easy to rearrange
Unknown number of cardsAuto-placement with repeat()No manual positions to maintain
Overlapping hero image and textLine-based placementItems can share cells and layer with z-index
Aligned content inside nested cardsSubgridChildren align to the parent tracks
Single row of controlsFlexbox instead of GridOne-dimensional distribution is simpler
Choosing a placement method

Alignment uses the Box Alignment properties shared with Flexbox: justify-items and align-items position items inside their cells, while justify-content and align-content position the entire grid inside the container when the tracks do not fill it.

Common mistakes and accessibility risks

The most serious risk in CSS Grid is a mismatch between visual order and source order. Screen readers and keyboard focus follow the HTML sequence, so moving items with order, explicit placement or dense packing can make tab navigation jump unpredictably across the screen.

SymptomCauseFix
Column overflows its shareImplicit auto minimum of 1frUse minmax(0, 1fr)
Focus order jumps aroundVisual placement differs from source orderReorder the HTML, not only the CSS
Unexpected extra rowsItems fall into implicit tracksDefine grid-auto-rows or fix spans
Nested items misalignedInner grid ignores parent tracksUse grid-template-columns: subgrid
Margins collapse expectationsGrid items do not collapse marginsUse gap for gutters
Typical grid problems and their fixes

Another common error is rebuilding a grid system with utility classes that recreate a twelve-column framework. Native CSS Grid makes most of that markup unnecessary, and fewer wrapper elements simplify both styling and the accessibility tree.

A plain-language summary

CSS Grid is a way of telling a web browser to lay out a page like a sheet of graph paper. The designer decides how many columns and rows there are and how wide each one should be, and then drops each piece of content into its place.

Before it existed, building a neat page with a header, a sidebar and a main area required workarounds. Now the layout is described in a few lines, and the browser does the arithmetic. The key point is simple: Grid handles rows and columns together, which is why it suits whole pages and galleries.

An example from practice

A front-end developer at an online retailer rebuilds the product listing page, which previously used a float-based framework with separate markup for phones, tablets and desktops. The new container uses grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)) with a gap of 1.5rem, so the page shows two columns on a phone and five on a wide monitor without a single breakpoint.

Each product card is itself a grid with grid-template-rows: subgrid, so images, titles, prices and buttons align across the whole row even when product names wrap to different lengths. The page skeleton around the listing uses named areas for the header, filters and results, and one media query swaps the filters from a sidebar to a top bar.

The result is roughly a third less layout CSS, the removal of several wrapper elements, and a keyboard order that still follows the HTML, because the team kept the source order identical to the visual order.