# How to Build a CSS Grid Layout (with Real Examples)

> A practical guide to CSS Grid: when to use it (and when flexbox is the better choice), the six properties that matter, how named lines and areas work, and how to experiment with a live layout in your browser before committing it to a stylesheet.

URL: https://uttir.com/blog/how-to-build-a-css-grid-layout
Published: 2026-08-25
Updated: 2026-08-17
Author: Uttir
Reading time: 7 min
Tags: css, grid, layout, web-design, frontend

## Quick answer

CSS Grid is the right layout model for two-dimensional layouts: any case where items need to align across both rows and columns. The six properties that matter are display, grid-template-columns, grid-template-rows, grid-template-areas, gap, and place-items. The most common mistakes are using grid for one-dimensional layouts (use flexbox for that) and over-specifying the layout (let auto-flow do the work). A browser playground lets you edit the values and see the result live, which is the fastest way to learn the model.

CSS Grid is the layout model for two-dimensional layouts. Where flexbox arranges items along a single axis, grid arranges them along two. The two are complementary: flexbox for a row or a column, grid for a real two-dimensional structure. This post covers when to reach for grid (and when to stay with flexbox), the six properties that matter, the named-areas shortcut, and how to experiment with a live layout in your browser before committing it to a stylesheet.

## When to use grid (and when not to)

Grid is for two-dimensional layouts: items that need to align across both rows and columns, where the relationship between items matters as much as the items themselves. Concrete cases:

	
- **A page layout with header, sidebar, main content, and footer.** The sidebar spans multiple rows; the main content area is the rest. The grid encodes the structure.
	
- **A photo gallery with consistent rows and columns.** All rows the same height, all columns the same width, and any cell can be made larger (a featured photo spanning 2 columns, a captioned photo spanning 2 rows).
	
- **A dashboard with widget cards.** Each widget occupies a specific cell or group of cells, and the layout is consistent across the dashboard.
	
- **A form with labeled fields.** The label column and the input column align across all rows.

Grid is *not* the right tool for one-dimensional layouts. If you have a row of items that should distribute horizontally, or a column of items that should distribute vertically, flexbox is the simpler choice. The two coexist in most real layouts: the page itself is a grid, and each row of the grid is a flex container.

## The six properties that matter

For most layouts, you only need these six properties. Together they describe the entire grid structure.

### display: grid

Turns the container into a grid container. Its direct children become grid items. This is the only mandatory declaration to start using grid.

### grid-template-columns

Defines the columns. The most common pattern is the responsive auto-fit:

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

This creates as many 250px-or-larger columns as fit, and stretches each to fill its share of the available space. The result is a responsive grid that shows 1 column on phones, 2 on tablets, 3 on small laptops, 4 on desktops, with no media queries. This single line replaces most of the responsive-grid CSS you have ever written.

### grid-template-rows

Defines the rows. Less commonly specified than columns; usually `auto` is enough (rows size to their content). The cases where you want to specify rows: a fixed-height header and footer, a dashboard with rows of specific heights, a masonry-like layout where rows are explicitly sized.

### grid-template-areas

Names the cells of the grid so the placement is readable. Example for a classic page layout:

grid-template-areas:
  "header header header"
  "sidebar main main"
  "footer footer footer";

Then the items use `grid-area: header`, `grid-area: sidebar`, etc. The layout is readable in the CSS itself, without counting lines. The dots (`.`) represent unnamed cells.

### gap

The space between rows and columns. Same as in flexbox. `gap: 16px` adds 16px between every adjacent row and column. Cleaner than `margin` on individual items.

### place-items

Shorthand for `align-items` and `justify-items` at the cell level. The most common value is `place-items: center`, which centers each item within its cell. The default is `stretch`, which makes each item fill its cell.

## Auto-flow: let the browser do the work

One of the most useful features of grid is `grid-auto-flow`. The default is `row`, which means the browser fills the grid one row at a time, placing each new item in the next available cell. For most layouts, this is exactly what you want: you do not need to specify the position of every item.

The alternative is `grid-auto-flow: column`, which fills the grid one column at a time. This is rarer, but useful for cases where the natural order is column-first (e.g. a list of items in a magazine layout).

The third option is `grid-auto-flow: dense`, which lets the browser backfill earlier cells with later items if they fit. This is useful for a photo gallery where you want to fill gaps, but can also cause out-of-order rendering that affects accessibility. Use with care.

## Spanning rows and columns

Any grid item can span multiple rows or columns. The syntax:

.featured {
  grid-column: span 2;
  grid-row: span 2;
}

This is the cleanest way to make a "featured" item larger than its neighbors in a photo gallery, or to make a sidebar span the full height of a page. The same effect with named areas:

grid-template-areas:
  "header header header"
  "sidebar main featured"
  "sidebar main featured"
  "footer footer footer";

Both syntaxes work; the named-areas version is more readable for non-trivial layouts.

## A practical example: a responsive photo gallery

A photo gallery that shows 1, 2, 3, or 4 columns depending on the viewport width, with a featured photo spanning 2 columns. The CSS is six lines:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.gallery .featured {
  grid-column: span 2;
}

That is the entire layout. The browser handles the responsive column count, the gap adds the spacing, and the featured photo spans 2 columns when there is room (and 1 when there is not, because grid is graceful about that).

## Another example: a page layout with named areas

A page with a header, sidebar, main content, and footer, where the layout is described in plain English:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
}

.page > header { grid-area: header; }
.page > aside { grid-area: sidebar; }
.page > main { grid-area: main; }
.page > footer { grid-area: footer; }

That is the entire layout. The HTML stays semantic (header, aside, main, footer), the CSS is readable, and the layout is responsive (the sidebar collapses to 100% width on small screens with one media query).

## Common gotchas

### 1. Using grid for one-dimensional layouts

Grid is for two-dimensional layouts. If you have a single row of items, flexbox is the simpler choice. The visual difference is small for a single row, but the CSS is clearer when each layout model is used for its purpose.

### 2. Forgetting to set the container to display: grid

The most common bug: writing all the grid-template-columns, grid-template-rows, and grid-template-areas on a container, but forgetting `display: grid`. The result is a normal block container, not a grid, and the items stack vertically as if nothing was specified.

### 3. Over-specifying the grid

You do not need to specify every cell. With `grid-auto-flow: row` (the default), the browser places items in the next available cell automatically. Specify only the structural properties (columns, areas, gap); let the browser handle the placement.

### 4. Using the wrong gap syntax

`grid-gap` is the old name. The current name is just `gap` (which works in both flex and grid). The old name still works for backward compatibility, but the new name is the right one to use in new code.

### 5. Mixing percentage and fr units without thinking about it

`1fr` means "one share of the available space after the non-fr tracks are sized". If you mix `200px` and `1fr`, the `1fr` track gets whatever is left after the 200px is allocated. If you mix `50%` and `1fr`, the `1fr` track gets whatever is left of the 50% — which can be 0 if the available space is exactly 50%. The fix: use `fr` units consistently, or use `minmax` to set a floor.

## How to experiment without writing a full HTML file

The [CSS Grid Playground](/css-grid-playground) on this site is an interactive editor. You write the grid CSS on the left, see the layout on the right, and the result updates live as you type. The playground comes with example layouts (photo gallery, page layout, dashboard) so you can see what each property does, then modify the values to match your use case.

The advantage of the playground over a real stylesheet: you can change one property at a time, see exactly what each one does, and undo if you go down a wrong path. For learning grid or for prototyping a layout, the playground is faster than the edit-reload loop of a real stylesheet.

## For the production stylesheet

Once you have the layout right in the playground, the same CSS goes into your stylesheet. The properties are the same, the values are the same, and the result is the same.

For the production site, the [CSS Minifier](/css-minifier) takes the layout CSS (plus the rest of your stylesheet) and produces the minified version that ships to the browser. The minified version is functionally identical, just smaller.

## When to use flexbox vs. grid

The mental model that works for most cases:

	
- **Flexbox:** one-dimensional layout. A row or a column. Items are independent; the alignment within the row (or column) is the question.
	
- **Grid:** two-dimensional layout. Rows AND columns matter. Items have a relationship to each other in both dimensions.

For a real page, the two coexist: the page itself is a grid (header, sidebar, main, footer), and each row of the grid is a flex container (navigation links, form fields, card content). The two layout models are not competing; they are complementary.

## A short checklist for new grid layouts

	
- Is this a two-dimensional layout? If yes, grid. If no, flexbox.
	
- How many columns? `grid-template-columns` with the auto-fit pattern for most responsive cases.
	
- Are there named regions? `grid-template-areas` for readable structural layouts.
	
- How much space between rows and columns? `gap`.
	
- Do any items span multiple rows or columns? `grid-column: span N` on the items that need it.

Six properties. That is the entire grid vocabulary for most layouts. The rest is the same kind of layout thinking you would do for any design — but grid makes the two-dimensional structure explicit and easy to maintain.

## Key takeaways

- When to use grid (and when not to)
- The six properties that matter
- Auto-flow: let the browser do the work
- Spanning rows and columns
- A practical example: a responsive photo gallery

## Frequently asked questions

### Is this free to use?

Yes. The tools and guides on Uttir are free to use, with no signup, no paywall, and no feature gating. There is no email gate, no trial period, and no premium tier. The site is supported by unobtrusive on-page ads that never interfere with the tool itself.

### Do I need to sign up or create an account?

No. Uttir does not have accounts, login, or email signup. Open the tool or the post and use it.

### Does this upload my data to a server?

Uttir processes your data entirely in your browser using JavaScript. Your text, files, and inputs are never uploaded to a server. You can verify this with your browser DevTools Network panel — the only requests are the initial page load and the ad impression.

### What tool should I use after reading this?

The most relevant tool on Uttir for this is the Css Grid Playground at [/css-grid-playground](/css-grid-playground). Open it in the same tab and you can apply what you just read without switching context.

## Related tools

- [CSS Grid Playground](https://uttir.com/css-grid-playground) — Visual playground for CSS Grid. Define rows, columns, and gaps, place items by area or line number, and copy the generated CSS.
- [CSS Flexbox Playground](https://uttir.com/css-flexbox-playground) — Visual playground for CSS Flexbox. Adjust container and item properties with sliders, see the live layout update, and copy the generated CSS.
- [CSS Gradient Generator](https://uttir.com/css-gradient-generator) — Build linear and radial CSS gradients visually. Pick colors, drag stops, copy the CSS.
- [CSS Box Shadow Generator](https://uttir.com/css-box-shadow-generator) — Visually design CSS box-shadows. Adjust offset, blur, spread, color, and inset. Stack multiple shadows for layered effects. Get the generated CSS instantly.
- [CSS Border Radius Generator](https://uttir.com/css-border-radius-generator) — Visually design CSS border-radius values. Independent corner control, preset shapes, live preview, and copyable CSS. Includes the "organic" 8-value syntax.
- [Color Palette Generator](https://uttir.com/color-palette-generator) — Generate 5-color palettes from any base color using classic harmony schemes — analogous, complementary, triadic, and more.
- [HTML Minifier](https://uttir.com/html-minifier) — Shrink HTML by stripping comments and collapsing whitespace. See byte savings in real time.
- [CSS Minifier](https://uttir.com/css-minifier) — Shrink CSS by stripping comments, collapsing whitespace, and tightening punctuation. See byte savings live.

---

For the full HTML article, visit https://uttir.com/blog/how-to-build-a-css-grid-layout.
This file is the markdown rendering at https://uttir.com/blog/how-to-build-a-css-grid-layout.md. See https://uttir.com/llms.txt for a site-wide summary.
