In short
This CSS Grid tutorial shows you how to build layouts with rows and columns using grid-template-columns, the fr unit, repeat(), gap, and how to place items with grid-column and span. What is CSS Grid? CSS Grid is a layout system for two directions at once: rows and columns.
This CSS Grid tutorial shows you how to build layouts with rows and columns using grid-template-columns, the fr unit, repeat(), gap, and how to place items with grid-column and span.
What is CSS Grid?
CSS Grid is a layout system for two directions at once: rows and columns. Flexbox arranges items in one line; Grid arranges them in a table-like structure, where you decide the size of every column and row.
Think of a chocolate bar or a sheet of graph paper. You draw the lines first, then you put items into the squares.
Like Flexbox, Grid has a parent and children:
- The grid container – the parent, with
display: grid. - The grid items – its direct children.
A few new words:
- Grid lines – the invisible lines between columns and rows. They are numbered from 1.
- Grid track – one column or one row.
- Grid cell – one square where a row and a column meet.
How to create columns and rows with grid-template-columns
grid-template-columns sets how many columns you want and how wide each one is. Each value is one column. grid-template-rows does the same for rows, but you often skip it and let rows be as tall as their content.
<section class="dashboard">
<div class="stat">Students: 1,240</div>
<div class="stat">Courses: 18</div>
<div class="stat">Lessons: 312</div>
<div class="stat">Projects: 45</div>
<div class="stat">Quizzes: 96</div>
<div class="stat">Hours: 870</div>
</section>
.dashboard {
display: grid;
grid-template-columns: 200px 200px 200px;
gap: 16px;
padding: 16px;
}
.stat {
background: #eff6ff;
border: 1px solid #bfdbfe;
border-radius: 10px;
padding: 20px;
font-family: system-ui, sans-serif;
font-weight: 600;
}
You see three columns, each 200 pixels wide, and the six stats fill them row by row: three on the first row and three on the second. The browser creates the second row automatically. gap adds space between rows and columns, just like in Flexbox.
What is the fr unit in CSS Grid?
Fixed pixel widths don't adapt to the screen. The fr unit (short for "fraction") means "a share of the free space". It is like cutting a cake: 1fr 1fr 1fr gives three equal slices, and 2fr 1fr gives one slice twice as big as the other.
grid-template-columns: 1fr 1fr 1fr;– three equal columns.grid-template-columns: 2fr 1fr;– the first column is twice as wide as the second.grid-template-columns: 250px 1fr;– a fixed 250px sidebar, and the rest for the content.
Writing 1fr many times gets boring, so CSS has repeat(). repeat(4, 1fr) is the same as 1fr 1fr 1fr 1fr. You can mix it too: repeat(2, 1fr) 300px.
Tip:
frshares the space that is left after the gaps and fixed sizes. So withgap, you never need to do maths likecalc(33.33% - 16px). Grid does it for you.
Common mistake: Using percentages like
33.33% 33.33% 33.33%together withgap. The gaps are added on top, so the grid becomes wider than its container and overflows. Use1frinstead.
Placing items with grid-column, grid-row and span
By default, items fill the cells one by one. You can also tell an item exactly where to go, using the numbered grid lines. A grid with three columns has four vertical lines: 1, 2, 3 and 4.
grid-column: 1 / 3;– start at line 1 and end at line 3, so the item covers two columns.grid-column: span 2;– cover two columns, starting wherever the item would be.grid-column: 1 / -1;– from the first line to the last line, the full width. Negative numbers count from the end.grid-row: span 2;– cover two rows.
Here is a magazine-style news layout:
<section class="news">
<article class="story big">Main story: New CSS features in 2026</article>
<article class="story">Grid tips</article>
<article class="story">Flexbox tricks</article>
<article class="story wide">Weekly coding challenge: build a photo gallery</article>
<article class="story">Q and A</article>
</section>
.news {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 140px;
gap: 16px;
padding: 16px;
}
.story {
background: #f3f4f6;
border-radius: 10px;
padding: 16px;
font-family: system-ui, sans-serif;
}
.big {
grid-column: span 2;
grid-row: span 2;
background: #fde68a;
font-size: 1.5rem;
font-weight: bold;
}
.wide {
grid-column: 1 / -1;
background: #dbeafe;
}
The main story is a big yellow block that covers two columns and two rows. The two small stories stack on the right side of it. The coding challenge stretches across the full width below, and the "Q and A" story starts a new row. grid-auto-rows: 140px makes every automatically created row 140 pixels tall.
Note:
grid-auto-rowssets the height of rows you didn't define yourself.minmax(140px, auto)is a safer value, because it lets a row grow taller if the content needs more room.
Practice exercise
Build a photo grid with four equal columns. Make the first photo span two columns and two rows, and make one photo near the end span the full width as a banner.
Hint: use grid-template-columns: repeat(4, 1fr);, then grid-column: span 2; grid-row: span 2; for the first photo and grid-column: 1 / -1; for the banner. Add width: 100%; height: 100%; object-fit: cover; to the images so they fill their cells.
Key takeaways
display: gridcreates a grid container; its direct children become grid items.grid-template-columnsandgrid-template-rowsset the size of each track.- The
frunit shares the free space;repeat(3, 1fr)makes three equal columns. gapadds space between rows and columns without any maths.- Use
grid-columnandgrid-rowwith line numbers orspanto place and size items.