CSS Grid Layout Basics
Learn CSS Grid: build two-dimensional layouts with grid-template-columns, rows, gap, fr units, repeat() and grid spanning. Includes a full responsive photo-gallery example, a try-it section and a quiz.
Key takeaways
- display: grid creates a two-dimensional layout of rows AND columns
- grid-template-columns defines how many columns there are and how wide they are
- The fr unit splits leftover space into flexible fractions
- repeat() and gap keep grid definitions short and evenly spaced
- grid-column: span 2 lets an item stretch across multiple tracks
A grid for two directions
CSS Flexbox is brilliant for arranging things in a single line β a row of buttons or a column of cards. But real page layouts often need control in two directions at once: a header across the top, a sidebar on the left, content in the middle, all in neat rows and columns. That's exactly what CSS Grid is built for.
Grid is a two-dimensional layout system. You define a set of columns and rows on a container, and then place items into the cells of that grid. In this lesson you'll learn the core properties and build a responsive photo gallery.
Step 1: turn on the grid
Just like Flexbox, Grid starts on the container. Set display: grid and then describe the columns:
.gallery {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
With HTML like:
<div class="gallery">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>
grid-template-columns: 1fr 1fr 1fr says "make three columns, each one fraction wide." The six cells flow into the grid three across, automatically wrapping onto new rows.
The fr unit
The star of Grid is the fr unit, short for fraction. It divides up the leftover space in the container. If you write three 1fr columns, each takes one third. Write 2fr 1fr 1fr and the first column is twice as wide as the others:
.layout {
display: grid;
grid-template-columns: 2fr 1fr 1fr; /* 50% / 25% / 25% */
}
Unlike percentages, fr automatically accounts for the gap between tracks, so your columns never overflow. You can also mix units β 250px 1fr gives a fixed 250px sidebar and a flexible main area that takes the rest.
Step 2: repeat() and gap
Writing 1fr 1fr 1fr 1fr gets tedious. The repeat() function shortens it:
.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr); /* four equal columns */
gap: 16px; /* space between cells */
}
gap adds even spacing between every row and column β no margins required. You can set them separately with row-gap and column-gap if needed.
Step 3: spanning across cells
By default each item fills one cell. To make an item stretch across more, use grid-column or grid-row with span:
.feature {
grid-column: span 2; /* take up two columns */
grid-row: span 2; /* and two rows */
}
This is how you build a magazine-style layout where one big image dominates while smaller items fill in around it.
Step 4: a responsive grid with no media queries
Here's a trick that feels like magic. Combine repeat() with auto-fit and minmax():
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 16px;
}
This reads as: "fit as many columns as you can, where each is at least 150px wide but can grow to share the space." On a wide screen you might get five columns; on a phone it collapses to one β all without a single media query. (When you do want explicit breakpoints, see Responsive Web Design Basics.)
A complete worked example
Save this as gallery.html and open it. Resize the window and watch the columns appear and disappear automatically.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Grid Gallery</title>
<style>
body { font-family: sans-serif; margin: 0; padding: 24px; background: #0f172a; }
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 16px;
}
.tile {
background: #38bdf8;
color: #0f172a;
font-size: 2rem;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
aspect-ratio: 1; /* keeps each tile square */
border-radius: 12px;
}
/* Make the first tile a big feature spanning 2 x 2 */
.tile.feature {
grid-column: span 2;
grid-row: span 2;
background: #f472b6;
aspect-ratio: auto;
}
</style>
</head>
<body>
<div class="gallery">
<div class="tile feature">β
</div>
<div class="tile">1</div>
<div class="tile">2</div>
<div class="tile">3</div>
<div class="tile">4</div>
<div class="tile">5</div>
<div class="tile">6</div>
<div class="tile">7</div>
</div>
</body>
</html>
Reading the result: the container is a responsive grid that fits as many 150px+ columns as the screen allows. The first tile carries the feature class, so it spans two columns and two rows to become a focal point. Inside each tile, Flexbox (display: flex) centers the number β Grid and Flexbox cooperating, each doing what it does best.
Try it yourself
- Change the minimum. Set
minmax(100px, 1fr)and thenminmax(250px, 1fr). Watch how the column count changes at the same window width. - Move the feature. Add the
featureclass to a different tile and see the others reflow around the larger cell. - Make a page layout. Build a new grid with
grid-template-columns: 200px 1frand two rows for a classic sidebar-plus-content layout. Add a header that spans both columns withgrid-column: span 2.
Challenge: Build a simple dashboard. Use a grid with a top header that spans the full width, a sidebar on the left, and a main area on the right split into a repeat(auto-fit, minmax(...)) grid of stat cards. Style the cards with a background, padding and border-radius, and use Flexbox inside each card to align a label and a number.
Quick quiz
Test yourself and earn XP
What makes CSS Grid different from Flexbox?
Flexbox lays out items in one direction; Grid handles rows and columns at the same time.
What does grid-template-columns: 1fr 1fr 1fr create?
Three 1fr tracks each take an equal fraction of the available width β three equal columns.
What does the fr unit represent?
fr stands for 'fraction' β it divides the remaining free space among the tracks.
What does repeat(4, 1fr) mean?
repeat(4, 1fr) is shorthand for writing 1fr 1fr 1fr 1fr β four equal columns.
How do you make one item span two columns?
grid-column: span 2 tells an item to stretch across two column tracks.
FAQ
Use Grid when you need control in two dimensions at once β a page layout, a photo gallery, a dashboard with rows and columns. Use Flexbox for a single row or column, like a navbar or a toolbar. They work beautifully together: Grid for the overall page skeleton, Flexbox inside individual cells.
minmax(min, max) sets a track that is never smaller than 'min' and never larger than 'max'. Combined with auto-fill or auto-fit and repeat(), it lets a grid automatically add or remove columns as the screen resizes β a responsive grid with no media queries needed.
Keep exploring
More in Coding