Learn
🤖 AI Hub 📰 News 📖 Dictionary 🧰 Resources
Grow
💼 Jobs 🚀 Community 🏆 Challenges
Explore by Stage
🌑 Zero 📚 Learn 🔧 Practice 🏗 Build 🚀 Launch 💰 Earn
Account
Login Sign Up
🏗️HTML 🎨CSS ⚡JavaScript 🐙Git & GitHub ⚛️React Soon 📘TypeScript Soon 🐍Python 🗄️Database & SQL Soon 🌐Web Development Soon ☁️Cloud & DevOps Soon 🤖AI & ML Soon 📄Resume Prep Soon 🎤Interview Prep Soon 💼Freelancing Soon 🚀SaaS & Side Projects Soon 🤖Automation Soon
Intermediate 🕑 12 min read 👁 3 views 📅 Oct 21, 2026

CSS Grid Basics: Rows, Columns and Gaps

Learn CSS Grid step by step: create columns and rows with px, fr and repeat(), add gaps, and make items span several cells, by building a college fest photo gallery.

The College Fest Gallery Problem

Your college fest is over. The photography club has hundreds of photos: the main stage, the rangoli competition, the food stalls and the dance finals. The student council asks you to put the best ones on the fest website, neatly, in rows and columns, with one big photo of the opening night.

You could try this with Flexbox, which you met in the CSS Flexbox lesson. Flexbox is great for a single row of items, but making photos line up perfectly in both rows and columns, with one photo stretching across two rows, is hard work. This is exactly the job CSS Grid was made for.

In this lesson you will learn how to turn any box into a grid, how to size columns and rows, how to add space between them, and how to make one item cover several cells.

Your First Grid: display: grid

A grid has two parts. The grid container is the parent element. You give it display: grid. Its direct children automatically become grid items, and the browser places them into cells, one after another, left to right and then down to the next row.

On its own, display: grid gives you just one column. You decide the columns with grid-template-columns. Each value you write creates one column of that width:

<style>
  .gallery {
    display: grid;
    grid-template-columns: 150px 150px 150px;
    gap: 12px;
  }
  .gallery div {
    background: #fde68a;
    padding: 20px;
    text-align: center;
    border-radius: 8px;
  }
</style>

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

Three values, so three columns. The six photos fill two rows on their own. You did not create the second row: the browser made it because there were more items than cells. The gap property adds space between the cells, but not around the outside edge.

The fr Unit: Sharing Free Space

Fixed widths like 150px are risky. On a wide laptop they leave empty space, and on a small phone they overflow. Grid has its own unit for this: fr, short for fraction. One fr is one share of the free space in the container.

<style>
  .page {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    gap: 10px;
  }
  .page div {
    background: #bfdbfe;
    padding: 20px;
    text-align: center;
  }
</style>

<div class="page">
  <div>1fr</div>
  <div>2fr (twice as wide)</div>
  <div>1fr</div>
</div>

Here the space is cut into 4 shares (1 + 2 + 1). The middle column gets 2 shares, so it is always twice as wide as each side column, on any screen. The gap is taken away first, and then the rest is shared out.

You can also mix units. grid-template-columns: 200px 1fr gives a fixed 200 pixel sidebar and lets the main area take everything else.

repeat(), Rows and Gaps

Writing 1fr 1fr 1fr 1fr is boring and easy to get wrong. The repeat() function does it for you: repeat(4, 1fr) means “four columns of 1fr each”.

Rows work the same way:

  • grid-template-rows sets the height of the rows you list.
  • grid-auto-rows sets the height of any extra rows the browser creates by itself.
  • gap with two values sets the row gap first, then the column gap. You can also write row-gap and column-gap separately.
<style>
  .gallery {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 100px 60px;
    grid-auto-rows: 80px;
    gap: 10px 20px;
  }
  .gallery div {
    background: #c7d2fe;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
  }
</style>

<div class="gallery">
  <div>1</div><div>2</div><div>3</div><div>4</div>
  <div>5</div><div>6</div><div>7</div><div>8</div>
  <div>9</div><div>10</div><div>11</div><div>12</div>
</div>

Look at the result. The first row is 100px tall and the second is 60px, as we listed. Row three was not listed, so it uses grid-auto-rows: 80px. If you leave rows out completely, each row is just as tall as its tallest item, which is often what you want.

Open DevTools. Right-click the grid, choose Inspect, and click the small grid badge next to the element. Chrome, Edge and Firefox then draw the grid lines and line numbers on the page. It is the fastest way to understand any grid.

Placing Items: Grid Lines and span

Between and around every column there is a grid line. A grid with 4 columns has 5 vertical lines, numbered 1 to 5 from the left. Rows have numbered lines too. You can tell an item where to start and end using these numbers:

CodeMeaning
grid-column: 1 / 3Start at column line 1, end at line 3 (covers 2 columns)
grid-column: 1 / -1From the first line to the last line (full width, for any number of columns)
grid-column: span 2Cover 2 columns, starting wherever the item would normally go
grid-row: span 2Cover 2 rows
<style>
  .board {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 70px;
    gap: 8px;
  }
  .board div {
    background: #e5e7eb;
    padding: 8px;
    border-radius: 6px;
  }
  .board .banner {
    grid-column: 1 / 5;     /* from line 1 to line 5 */
    background: #fca5a5;
  }
  .board .wide {
    grid-column: span 2;    /* take 2 columns */
    background: #86efac;
  }
  .board .tall {
    grid-row: span 2;       /* take 2 rows */
    background: #93c5fd;
  }
</style>

<div class="board">
  <div class="banner">Banner: full width</div>
  <div class="tall">Tall</div>
  <div class="wide">Wide</div>
  <div>Small</div>
  <div>Small</div>
  <div>Small</div>
  <div>Small</div>
</div>

The banner covers lines 1 to 5, so it fills the whole first row. The tall box covers two rows, and the other items flow around it. Most of the time span is easier than line numbers, because you only say how big the item is and let the grid decide where it goes.

Grid or Flexbox?

Both are modern layout tools, and real websites use both. The main difference is the number of directions:

FlexboxGrid
DirectionsOne: a row or a columnTwo: rows and columns together
Who decides the sizeMostly the content of each itemMostly the container’s columns and rows
Good forNavigation bars, button groups, centring one thingGalleries, dashboards, full page layouts

Run this example and compare the last row in each box:

<style>
  .flex-row, .grid-box {
    gap: 8px;
    margin-bottom: 24px;
  }
  .flex-row {
    display: flex;
    flex-wrap: wrap;
  }
  .flex-row div {
    flex: 1 1 120px;
  }
  .grid-box {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }
  .flex-row div, .grid-box div {
    background: #fbcfe8;
    padding: 14px;
    text-align: center;
  }
</style>

<p>Flexbox (one direction, rows decide their own sizes):</p>
<div class="flex-row">
  <div>A</div><div>B</div><div>C</div><div>D</div><div>E</div>
</div>

<p>Grid (rows and columns line up):</p>
<div class="grid-box">
  <div>A</div><div>B</div><div>C</div><div>D</div><div>E</div>
</div>

With Flexbox, the last two items stretch to fill their row, so they do not line up with the items above. With Grid, D and E stay in the same columns as A and B. If you want things to line up in both directions, choose Grid.

Real-Life Example: The Utsav Fest Photo Gallery

Now let us build the gallery the student council asked for. It uses three equal columns, a fixed row height, a big featured photo that covers 2 columns and 2 rows, and a wide photo of the dance finals. The images come from an online placeholder service, so you need an internet connection to see them.

<style>
  body {
    font-family: system-ui, sans-serif;
    background: #1e1b4b;
    color: white;
    padding: 16px;
  }
  h2 { text-align: center; }
  .gallery {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 140px;
    gap: 10px;
  }
  .gallery figure {
    margin: 0;
    position: relative;
    border-radius: 10px;
    overflow: hidden;
  }
  .gallery img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .gallery figcaption {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 6px 10px;
    background: rgba(0, 0, 0, 0.6);
    font-size: 14px;
  }
  .featured {
    grid-column: span 2;
    grid-row: span 2;
  }
  .wide { grid-column: span 2; }
</style>

<h2>Utsav 2026: Photo Gallery</h2>
<div class="gallery">
  <figure class="featured">
    <img src="https://picsum.photos/seed/fest1/600/400" alt="Main stage on the opening night">
    <figcaption>Opening night, main stage</figcaption>
  </figure>
  <figure>
    <img src="https://picsum.photos/seed/fest2/300/300" alt="Rangoli competition">
    <figcaption>Rangoli</figcaption>
  </figure>
  <figure>
    <img src="https://picsum.photos/seed/fest3/300/300" alt="Food stalls">
    <figcaption>Food stalls</figcaption>
  </figure>
  <figure class="wide">
    <img src="https://picsum.photos/seed/fest4/600/300" alt="Dance team on stage">
    <figcaption>Group dance finals</figcaption>
  </figure>
  <figure>
    <img src="https://picsum.photos/seed/fest5/300/300" alt="Robotics workshop">
    <figcaption>Robotics workshop</figcaption>
  </figure>
</div>

Notice object-fit: cover on the images. It makes each photo fill its cell completely without stretching, by cutting off the extra edges. Every photo has a short alt text for people who use screen readers.

Try these changes:

  1. Change repeat(3, 1fr) to repeat(4, 1fr) and watch how the photos reflow.
  2. Remove the class featured from the first photo. What happens to the layout?
  3. Change gap: 10px to gap: 2px for a tight, magazine style look.

On a narrow phone, three columns may feel small. In the CSS Grid Layouts lesson you will learn a one-line trick that changes the number of columns by itself.

Common Mistakes

  • Putting display: grid on the items instead of the parent. Grid properties like grid-template-columns belong on the container. Only placement properties like grid-column go on the items. See the broken and fixed versions below.
  • Using margins for spacing. Margins on grid items add space on the outside edges too, and the numbers get confusing. Use gap on the container instead.
  • Fixed pixel columns everywhere. repeat(4, 250px) needs 1000 pixels and will overflow a phone screen. Prefer fr.
  • Counting columns instead of lines. grid-column: 1 / 3 covers 2 columns, not 3, because the numbers are lines. If this confuses you, use span.

Here the grid is on the wrong element, so each card becomes its own tiny grid and the cards stack:

<style>
  .card {
    display: grid;                     /* on the cards, not on the parent */
    grid-template-columns: 1fr 1fr 1fr;
  }
  .card { background: #fed7aa; padding: 12px; margin: 4px; }
</style>

<div class="cards">
  <div class="card">Dance</div>
  <div class="card">Music</div>
  <div class="card">Drama</div>
</div>

Move the grid to the parent .cards and the cards sit side by side:

<style>
  .cards {
    display: grid;                     /* on the parent */
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
  }
  .card { background: #fed7aa; padding: 12px; }
</style>

<div class="cards">
  <div class="card">Dance</div>
  <div class="card">Music</div>
  <div class="card">Drama</div>
</div>

Practice Task: The Fest Schedule Board

The fest committee wants a schedule board for Day 1. Use the starter code and complete the four TODO steps.

  • The board has 3 equal columns with a 12px gap.
  • The heading “Fest Schedule: Day 1” covers the full width.
  • The Battle of Bands box is twice as tall as the others, because it is the main event.
<style>
  body { font-family: system-ui, sans-serif; padding: 16px; }
  .events div {
    background: #ddd6fe;
    padding: 16px;
    border-radius: 8px;
  }
  /* TODO 1: make .events a grid with 3 equal columns */
  /* TODO 2: add a gap of 12px */
  /* TODO 3: make .headline span all 3 columns */
  /* TODO 4: make .highlight take 2 rows */
</style>

<div class="events">
  <div class="headline">Fest Schedule: Day 1</div>
  <div class="highlight">Battle of Bands, 7 PM</div>
  <div>Quiz, 10 AM</div>
  <div>Coding contest, 11 AM</div>
  <div>Treasure hunt, 2 PM</div>
  <div>Debate, 4 PM</div>
</div>
Show one possible answer (try it yourself first!)
<style>
  body { font-family: system-ui, sans-serif; padding: 16px; }
  .events div {
    background: #ddd6fe;
    padding: 16px;
    border-radius: 8px;
  }
  .events {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
  }
  .headline {
    grid-column: 1 / -1;
    font-weight: bold;
    text-align: center;
  }
  .highlight {
    grid-row: span 2;
  }
</style>

<div class="events">
  <div class="headline">Fest Schedule: Day 1</div>
  <div class="highlight">Battle of Bands, 7 PM</div>
  <div>Quiz, 10 AM</div>
  <div>Coding contest, 11 AM</div>
  <div>Treasure hunt, 2 PM</div>
  <div>Debate, 4 PM</div>
</div>

Key Takeaways

  • display: grid goes on the parent. Its direct children become grid items.
  • grid-template-columns and grid-template-rows set the size of each track. The fr unit shares out the free space.
  • repeat(4, 1fr) is a short way to write four equal columns.
  • gap adds space between cells, never on the outer edges.
  • Use grid-column and grid-row with line numbers or span to make an item cover several cells.
  • Flexbox is for one direction. Grid is for rows and columns together.

❓ Frequently Asked Questions

Yes. All modern browsers, including Chrome, Firefox, Safari and Edge on phones, have supported CSS Grid for many years, so you can use it safely.
No. They work well together. Many pages use Grid for the overall layout and Flexbox inside each card or menu.
Percentages are taken from the full container width and do not account for gaps, so columns plus gaps can overflow. The fr unit shares only the space left after gaps and fixed columns, so it always fits.
No. Any direct child of the grid container becomes a grid item: figure, article, img, a or any other element.
Was this lesson helpful?

🎯 Finished this lesson?

🔗 Related Tutorials
🤖 Got a Doubt? Ask AI
Get instant answers in Hindi or English
🤖
Z2T Bot
Online
Ask me anything about this tutorial — I'm here! 👋