CSS Grid

CSS Grid is a layout system for two dimensions: rows and columns at the same time. You define a grid of tracks on a container, and place items into cells or across areas, with precise alignment in both directions. Page layouts (header, sidebar, main, footer), image galleries, dashboards, pricing tables, and forms with aligned labels are all natural Grid territory.

Grid pairs with Flexbox. Flexbox excels at distributing items along one axis inside components, while Grid defines the overall structure. With repeat(), minmax(), auto-fit, and named areas, many responsive layouts need few or no media queries.

TL;DR

Quick Example

A classic application layout with named areas that restructures on small screens:

Core Concepts

Grid Terminology

Defining Tracks

auto-fit vs auto-fill

With repeat(auto-fill | auto-fit, minmax(240px, 1fr)), the browser creates as many columns as fit:

Wrap the minimum in min(240px, 100%) so a single column never overflows a narrow screen.

Placing Items

Lines can also be named (grid-template-columns: [full-start] 1fr [content-start] minmax(0, 60rem) [content-end] 1fr [full-end]), which enables "breakout" layouts where most content sits in a readable column while images span full width.

Named Areas

grid-template-areas draws the layout as ASCII art. Each string is a row, each word a cell, and . is an empty cell. Items opt in with grid-area: name. Redefining the template in a media or container query rearranges the whole layout without touching the HTML.

The Implicit Grid

Items beyond the explicit tracks create implicit tracks, sized by grid-auto-rows and grid-auto-columns. grid-auto-flow controls placement direction (row by default, or column), and dense backfills holes. That's useful for masonry-like galleries, though it changes visual order.

Alignment

Grid supports alignment on both axes, for the whole grid inside the container and for items inside their cells:

place-items: center on a grid container is the shortest way to center content.

Subgrid

grid-template-columns: subgrid (or rows) makes a nested grid use its parent's tracks. For example, cards in a row can align their titles, bodies, and footers across cards even when content lengths differ, which was previously impossible without fixed heights. It's supported in all modern browsers.

Best Practices

Use Grid for Structure, Flexbox for Components

Define page and section structure with Grid, then lay out component internals (toolbars, button rows, media objects) with Flexbox.

Guard Against Overflow With minmax(0, 1fr)

Long words, code blocks, or wide tables can force 1fr tracks wider than intended. minmax(0, 1fr) tracks, plus min-width: 0 on items, keep layouts contained.

Keep Source Order Logical

Grid lets you place items anywhere visually, but keyboard focus and screen readers follow DOM order. Keep the DOM in a sensible reading order and use placement for presentation. See accessibility.

Let Intrinsic Sizing Do the Work

auto-fit/minmax() patterns and content-based track sizes often eliminate breakpoints entirely. Combine them with container queries for truly component-driven responsiveness. See responsive design.

Common Mistakes

Grid Blowout From Long Content

Confusing auto-fill and auto-fit

With few items, auto-fill leaves empty columns and items stay narrow, while auto-fit stretches them. Choose based on whether items should grow to fill the row.

Recreating 12-Column Frameworks Everywhere

Wrapping everything in repeat(12, 1fr) with span classes reintroduces framework rigidity. Define tracks that match each layout's actual structure.

FAQ

When should I use Grid instead of Flexbox?

Use Grid when you need alignment in both rows and columns, or when the layout defines the structure and content fills it: page layouts, galleries, dashboards, forms. Use Flexbox when items flow in one direction and their size should drive spacing: navbars, toolbars, tag lists.

What does the fr unit mean?

A fraction of the remaining free space in the grid container, after fixed-size and content-sized tracks are accounted for. 1fr 2fr gives the second column twice the leftover space of the first.

How do I make a responsive grid without media queries?

grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)) automatically creates as many columns as fit, each at least 250px wide, collapsing to one column on narrow screens.

Is CSS masonry layout supported?

A native masonry layout for Grid (grid-template-rows: masonry, and alternative proposals) has been under specification and experimentation in browsers. Until it's broadly available, use grid-auto-flow: dense approximations, CSS columns, or a small JavaScript library.

Related Topics

References