CSS Grid is the layout system built for arranging content in rows and columns at the same time, which makes it the right tool whenever a design is two-dimensional rather than a single line of items. This CSS grid tutorial skips the long property-by-property reference (you can build and inspect every property live in our CSS Grid Generator) and instead focuses on worked examples: masonry-style galleries, image grids, and the real page layouts you actually end up shipping, like dashboards and holy grail templates.

A quick refresher before the examples

A grid has two parts: a container with display: grid, and the direct children inside it, which automatically become grid items. You control the shape of the grid with grid-template-columns and grid-template-rows, and the spacing between tracks with gap.

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

That is enough to follow every example below. If you want the full syntax reference, the fr unit explained in depth, repeat() and minmax(), named areas, or a live visual builder, that all lives on the CSS Grid Generator page.

Build the grid visually instead of by hand

Our CSS Grid Generator lets you set columns, rows, gaps and item placement with sliders and click-to-place controls, then copy the finished CSS straight out.

Open the CSS Grid Generator →

CSS Grid examples and layout patterns

These are the layout patterns that come up constantly once you start reaching for Grid instead of floats or Flexbox. Each one is a self-contained example you can drop straight into a project.

Equal-width card grid

The most common starting point: a set of cards that share the available width equally and wrap automatically.

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

Fixed sidebar with a flexible content column

A sidebar that keeps its width and a main column that takes up whatever space is left over.

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 24px;
}

An item that spans multiple tracks

Any grid item can take up more than one column or row by telling it how many tracks to span.

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

Centering content inside a grid

One of the shortest ways to center something on a page, no margin math involved.

.center {
  display: grid;
  place-items: center;
  min-height: 100vh;
}
Why not just Flexbox? Flexbox handles a single row or column well, but the moment items need to line up across both rows and columns at once, like a card grid where every row should share the same column widths, Grid is doing less fighting against the layout than Flexbox would.

CSS masonry layout with Grid

A masonry layout is the Pinterest-style grid where columns are even but rows are not: items sit as close to their neighbor above as possible, with no wasted vertical gap. Grid does not do this automatically, because every row in a standard grid is the same height across the whole row. There are three ways to get the effect.

1. The simplest option: CSS multi-column

If you do not specifically need Grid, plain multi-column layout produces true masonry with almost no code.

.masonry {
  column-count: 3;
  column-gap: 16px;
}
.masonry > * {
  margin-bottom: 16px;
}
The trade-off: multi-column fills items down each column first, so the visual reading order runs top-to-bottom then left-to-right. For a photo gallery that is usually fine; for a list of articles where order matters, it reads in the wrong sequence.

2. The Grid-based workaround: fixed row unit plus row spans

To keep left-to-right, top-to-bottom order and still get a masonry effect, set a small grid-auto-rows unit and give each item a grid-row: span value proportional to its own height.

.masonry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  grid-auto-rows: 10px;
  gap: 16px;
}
/* Roughly: span = ceil(itemHeight / 10px) */
.masonry-grid .item {
  grid-row: span 24; /* ~240px tall item */
}

The span numbers can be set by hand for a fixed set of cards, or calculated with a few lines of JavaScript that read each item's rendered height and set its span automatically, which is the only way to get pixel-accurate spacing since content height is rarely known ahead of time.

3. The native option: grid-template-rows: masonry

The CSS Grid Level 3 draft adds a real masonry mode directly to Grid: grid-template-rows: masonry. It packs items into the shortest column automatically, with no manual spans and no JavaScript.

.masonry-native {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  grid-template-rows: masonry;
  gap: 16px;
}
Not production-ready yet: as of this writing, masonry only works behind a flag in Firefox. Treat it as something to watch, not something to ship, until support broadens.

Building an image gallery with CSS Grid

A responsive image gallery is one of the most direct real-world uses of everything above. The core pattern is a grid that adds or removes columns on its own as the viewport changes, with no media queries.

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.gallery img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 8px;
}

aspect-ratio keeps every tile square regardless of the source image's real dimensions, and object-fit: cover crops instead of stretching. To make one image stand out as a hero tile, span it across more tracks:

.gallery .featured {
  grid-column: span 2;
  grid-row: span 2;
}
Skip the hand-coding: the Image Gallery preset in the CSS Grid Generator already builds this exact pattern with an editable hero tile, if you would rather adjust sliders than write the CSS yourself.

Real-world grid layout patterns

Beyond individual components, Grid is where full page shells get built. The examples below use grid-template-areas, which reads like a diagram of the page and is easier to keep straight than counting line numbers once a layout has more than three or four regions.

The holy grail layout

Header across the top, a sidebar, a main content area, and a footer across the bottom, all in one declaration with no wrapper elements.

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

/* Stack the sidebar above the content on narrow screens */
@media (max-width: 700px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "sidebar"
      "main"
      "footer";
  }
}

Rearranging this layout for mobile only means retyping the map inside the media query. The individual elements never need their own responsive rules.

A dashboard with mixed-size widgets

Dashboards combine a fixed shell with a flexible content grid nested inside it. The outer grid handles the page structure; an inner grid handles the widget cards.

.dashboard-main {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
}
.widget.wide {
  grid-column: span 2;
}

Because the widget grid uses auto-fit with minmax(), it reflows on its own at any dashboard width, and the .wide widget simply claims two tracks whenever there is room for it.

Keeping this separate from the tool page: the CSS Grid Generator's own responsive section shows the auto-fit plus minmax() pattern in isolation. The layouts here go a step further by combining it with grid-template-areas into full page shells, which is the part that is easiest to get wrong on your own.

FAQ

What is an example of a CSS grid layout?

A simple example is a card grid: a container with display: grid and grid-template-columns: repeat(3, 1fr) creates three equal-width columns, and every direct child becomes a grid item that automatically flows into the next available cell. More advanced examples include holy grail page layouts built with grid-template-areas, masonry-style image galleries, and dashboards with widgets of different sizes, all covered further up this guide.

How do I create a grid in CSS?

Add display: grid to a container element, then define its tracks with grid-template-columns and grid-template-rows. Every direct child of that container automatically becomes a grid item and is placed into the grid without any extra markup. If you want to skip writing the syntax by hand, our CSS Grid Generator builds the same code visually and lets you copy it straight into your project.

Can you build a masonry layout with just CSS Grid?

Yes, with a workaround. Standard CSS Grid rows are uniform in height, so you fake the masonry effect by setting a small grid-auto-rows unit and giving each item a grid-row: span value based on its content height. A native masonry mode (grid-template-rows: masonry) exists in the CSS Grid Level 3 draft, but as of this writing it only ships behind a flag in Firefox, so it is not yet safe to rely on in production.

Do you need JavaScript for a CSS Grid image gallery?

No, not for a standard responsive gallery. A grid with grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)) and aspect-ratio on each image reflows automatically at any screen width with pure CSS. JavaScript only becomes useful if you want a pixel-accurate masonry gallery, where you calculate each image's exact row span from its rendered height.

What is the quickest way to build a responsive dashboard layout with CSS Grid?

Give the page container named areas with grid-template-areas for the sidebar, header and main content, then redefine those same area names inside a media query to collapse the sidebar above the content on narrow screens. Inside the main area, a second nested grid with repeat(auto-fit, minmax(...)) handles the widget cards without any extra breakpoints.

Should I use CSS Grid or CSS columns for a masonry-style gallery?

CSS multi-column layout (column-count) gives you a true masonry effect with zero extra code, but it fills items down each column first, so the reading order is top-to-bottom then left-to-right, which is wrong for content where order matters. CSS Grid keeps items in left-to-right, top-to-bottom source order, which is usually what you want for a gallery, at the cost of needing the row-span workaround covered earlier in this guide.