Quick Answer

CSS Grid is a layout system that lets you arrange elements into rows and columns at the same time. You set display: grid on a container, define columns and rows with grid-template-columns and grid-template-rows, add space with gap, and make items span multiple cells. With repeat() and minmax() you can build responsive grids that adjust to any screen without media queries.

What is CSS Grid, and why learn it

Welcome to this CSS Grid layout tutorial for beginners. If you have ever tried to line up cards, images, or sections on a page and ended up fighting with floats or endless margin hacks, Grid is the tool you were missing.

CSS Grid is a two-dimensional layout system. That single word, two-dimensional, is the whole point: Grid lets you control rows and columns at the same time. You draw an invisible table of cells on the screen, then drop your content into it. No tables in your HTML, no floats, no positioning tricks.

Everything happens on a container (the parent element) and its items (the direct children). You turn a normal element into a grid by giving it display: grid. That is the on switch for everything below.

.gallery {
  display: grid;
}

Right now nothing looks different because we have not told the grid how many columns to use. Let's fix that next.

Defining columns and rows

Two properties do the heavy lifting: grid-template-columns sets the vertical tracks, and grid-template-rows sets the horizontal tracks. You list a size for each track, separated by spaces.

.gallery {
  display: grid;
  grid-template-columns: 200px 200px 200px;
  grid-template-rows: 150px 150px;
}

This says: three columns, each 200px wide, and two rows, each 150px tall. That is a 3×2 grid of six cells. Your child elements flow into those cells automatically, left to right, top to bottom.

Say your HTML looks like this:

<div class="gallery">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

The six <div> boxes drop neatly into the six cells. You never had to say where item 4 goes; Grid places it for you. If you add a seventh item, Grid creates a new row on its own to hold it. That auto-created row is called an implicit row, and it is one reason Grid feels so forgiving for beginners.

fr units and gap: flexible, spaced-out grids

Fixed pixel widths are fine for practice, but real layouts need to stretch and shrink. That is what the fr unit is for. fr means fraction of the free space in the container.

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

This makes three columns that each take one equal share of the available width. Resize the window and they grow or shrink together, always staying equal. Compare that to 200px 200px 200px, which never changes.

You can also mix ratios. 2fr 1fr gives you two columns where the first is twice as wide as the second, perfect for a main-content-plus-sidebar layout. You can even mix units: 250px 1fr gives a fixed 250px sidebar and a flexible main area that eats the rest.

To add breathing room between cells, use gap. It sets the space between rows and columns without adding margins to individual items.

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
}

One value sets the gap on all sides between tracks. Want different row and column spacing? Pass two values: gap: 24px 16px; means 24px between rows and 16px between columns. Gotcha: gap only sits between cells, never on the outer edge of the grid. Use padding on the container if you want space around the whole thing.

Making items span multiple cells

So far every item fills exactly one cell. But a good gallery usually has one hero image that is bigger than the rest. Grid handles this with grid-column and grid-row.

Grid numbers the lines between and around tracks, starting at 1 on the left. A three-column grid has four vertical lines: 1, 2, 3, 4. You can tell an item to stretch from one line to another.

.featured {
  grid-column: 1 / 3; /* start at line 1, end at line 3 */
}

That makes the item cover the first two columns. The easier-to-read version uses the span keyword, so you do not have to count lines:

.featured {
  grid-column: span 2; /* cover 2 columns */
  grid-row: span 2;    /* and 2 rows */
}

Now that one item is a big 2×2 block, and every other item flows around it. This is the kind of layout that used to take hours with floats. With Grid it is two lines. The beauty is that the surrounding items rearrange themselves automatically to fill the leftover cells.

repeat() and minmax() for responsive grids

Typing 1fr 1fr 1fr 1fr for four columns is tedious, and it breaks on small screens. Two functions solve both problems.

repeat() is shorthand. repeat(3, 1fr) means exactly the same as 1fr 1fr 1fr. Cleaner, and easy to change the number.

grid-template-columns: repeat(3, 1fr);

minmax(min, max) sets a size range for a track. minmax(200px, 1fr) means never smaller than 200px, but grow to fill space when there is room.

The magic happens when you combine them with the keyword auto-fit:

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

Read it plainly: fit as many columns as you can, each at least 200px wide, and let them stretch to share the extra space. On a wide laptop you might get five columns; on a phone you get one, all with zero media queries. The grid responds to its own width. This one line is the single most useful pattern in all of CSS Grid, so it is worth memorising.

Tip: auto-fit collapses empty tracks so your items stretch to fill the row. Its cousin auto-fill keeps empty tracks reserved, which can leave gaps on the right. For most galleries, auto-fit is what you want.

Let's put every piece together into a working, responsive photo gallery with one featured image. Here is the full HTML and CSS. Copy it into a file and open it in your browser.

<div class="gallery">
  <img class="featured" src="photo1.jpg" alt="Sunrise">
  <img src="photo2.jpg" alt="Street">
  <img src="photo3.jpg" alt="Temple">
  <img src="photo4.jpg" alt="Coast">
  <img src="photo5.jpg" alt="Market">
  <img src="photo6.jpg" alt="Hills">
</div>
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  grid-auto-rows: 180px;
  gap: 12px;
  padding: 12px;
}

.gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}

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

What each part does: the container builds a responsive column count from repeat(auto-fit, minmax(...)). grid-auto-rows: 180px gives every implicit row a fixed height so the grid stays tidy. On the images, object-fit: cover crops each photo to fill its cell without stretching, which keeps everything neat even when photos have different shapes. The .featured image spans a 2×2 area to stand out.

Gotcha to watch: if the screen gets so narrow that only one column fits, a span 2 item cannot span two columns that do not exist, so it simply takes the full single column. That is fine, and it is Grid protecting your layout from breaking. Want to go deeper on selectors, the box model, and responsive design that pairs with this? Our free CSS course walks through it step by step.

Grid vs Flexbox: which one to use

Beginners often ask whether to use Grid or Flexbox. Here is the one-line rule: use Grid when you need to control rows and columns together (two dimensions); use Flexbox when you are laying items out in a single row or a single column (one dimension).

SituationGridFlexbox
Full page or gallery layout (rows + columns)YesNo
A navbar or row of buttonsPartialYes
Aligning items along one lineNoYes
Overlapping or spanning cellsYesNo

They are not rivals. In real projects you often use Grid for the overall page skeleton and Flexbox inside a grid cell to align a few items. Learn both, and reach for whichever matches the shape of the problem.

Common gotchas and next steps

A few things trip up beginners, so keep them in mind:

  • Grid properties go on the parent. display: grid, grid-template-columns, and gap belong on the container. Only grid-column and grid-row go on the children.
  • Only direct children become grid items. A grandchild deep inside an item is not placed by the grid; wrap or restructure if you need it in the grid.
  • Do not confuse fr with %. Percentages ignore the gap, which can cause overflow. fr accounts for the gap automatically, so prefer it.
  • Explicit vs implicit tracks. Rows you define get their size; extra rows Grid creates use grid-auto-rows. Set it so surprise rows still look right.

Now practice. Rebuild the gallery, change minmax(180px, 1fr) to different values, move the .featured class to another image, and watch what happens. Hands-on tweaking is how Grid clicks. When you are ready to fill the gaps around it, the free Priodemy CSS course covers responsive design, the box model, and modern layout end to end.

Frequently Asked Questions

Do I need to learn Flexbox before CSS Grid?

No, you can start with either. They solve slightly different problems: Grid handles two-dimensional layouts (rows and columns together) while Flexbox handles one-dimensional rows or columns. Many developers actually find Grid easier to reason about for page layouts. Learn Grid for structure, then pick up Flexbox for aligning small groups of items.

What does the fr unit mean in CSS Grid?

The fr unit means one fraction of the free space left in the grid container. If you write grid-template-columns: 1fr 1fr 1fr, the three columns split the available width equally. Using 2fr 1fr makes the first column twice as wide as the second. Unlike percentages, fr correctly accounts for the gap between cells, so it rarely causes overflow.

How do I make a CSS Grid responsive without media queries?

Use grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)). This tells the browser to fit as many columns as possible, each at least 200px wide, and stretch them to fill the row. The number of columns changes automatically as the screen resizes, so a single line replaces several media queries. Adjust the 200px value to control how many columns appear.

Why do my grid-column and grid-row properties not work?

The most common reason is putting them on the wrong element. Properties like display: grid, grid-template-columns, and gap go on the parent container, while grid-column and grid-row go on the child items. Also check that the item is a direct child of the grid container; nested elements deeper down are not placed by the grid.

Can I make one grid item bigger than the others?

Yes. Add grid-column: span 2 and grid-row: span 2 to that item so it covers a 2 by 2 block of cells. The other items automatically flow around it. This is the standard way to build a featured or hero image in a photo gallery, and it works without any change to your HTML order.

Is CSS Grid supported in all browsers?

CSS Grid is supported in every modern browser, including Chrome, Firefox, Safari, and Edge, on both desktop and mobile. It has been stable and widely available for years, so you can use it confidently for production websites. Only very old browsers lack support, and for a learning project or a modern site that is not a concern.