Open the IRCTC ticket booking page in your head for a second. Across the top there is a search bar. Below it, a strip of quick filters. Below that, a big table of trains with columns for train number, name, departure time, duration, and seat availability, and every one of those columns lines up perfectly for every single row. Now imagine trying to build that page using only what you may have used so far in HTML and CSS — a bunch of <div> boxes with margin and manually chosen widths, stacked one after another. The moment one train's name is longer than another's, everything to its right shifts, and the neat columns fall apart. You would spend hours nudging pixel values around, and the layout would still break the next time content changed.
This is exactly the problem CSS Grid was built to solve. It gives a webpage the same structure as a sheet of graph paper or the seating chart your class teacher pastes on the classroom wall — a fixed set of rows and columns that every item can be placed into by position, so that things line up automatically and stay lined up even when content changes. In this chapter you will learn how to think in that grid, do the arithmetic CSS Grid does under the hood to size rows and columns, and place items on it precisely.
Why Not Just Use display: block?
By default, every <div> in HTML is a block-level box. Block boxes stack vertically, one under another, each taking the full width available. That is a one-dimensional idea — it only really controls the vertical direction; the horizontal direction is left to whatever width you set. If you want three boxes to sit side by side and two rows below them to also line up in columns with the boxes above, block layout gives you no built-in way to describe that. You end up faking columns with widths and margins that have to be recalculated by hand whenever anything changes.
CSS Grid changes the unit of layout. Instead of positioning one box at a time, you first declare a grid — a number of columns and rows with specific sizes — on a parent element, and then every direct child of that parent is automatically dropped into the next empty cell of that grid, left to right, top to bottom, rather like how photographs get dropped into slots on a printed collage template. You can also explicitly tell a specific child which row and column it belongs to, and even how many cells it should span. That is the whole idea. Everything else in this chapter is about the vocabulary CSS gives you to describe that grid precisely.
Turning a Container Into a Grid
Grid is switched on with one line: display: grid; on the parent element. On its own, that line does very little visually — it just tells the browser "I am about to describe rows and columns for this element's children." You describe the columns with grid-template-columns and the rows with grid-template-rows, giving a size for each track (a "track" is CSS Grid's word for one row or one column).
.gallery {
display: grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 150px 150px;
}
Read that grid-template-columns line the way you would read a sentence: it says "there are three columns, and each one is 200 pixels wide." Any direct child <div> of .gallery — say, six photo cards for an Independence Day event — will automatically flow into this 3-column, 2-row grid: the first three cards fill row one, the next three fill row two. You did not write a single margin or float. The browser did the placement arithmetic for you, because you described the structure instead of describing each box's position by hand.
The fr Unit: Sharing Space the Way You Share Marks
Fixed pixel widths are useful sometimes, but most real layouts need to say "give this column a share of whatever space is left," not "give it exactly 200px." CSS Grid has a special unit for this called fr, short for fraction. Think of it exactly the way your class might divide 100 marks between three project components in the ratio 1 : 1 : 2 — the actual number of marks each component gets depends on how the "100" is split according to those ratios.
Here is the precise rule, and it is worth being exact about it because this is the single most common point of confusion with CSS Grid: the browser first lays out every column that has a fixed size (like 200px), then subtracts the total width used by any gap between columns, and only then divides whatever width is left among the columns sized in fr, in proportion to their fr numbers. The fr unit is a fraction of the leftover space, not a fraction of the container.
Let's actually compute an example, the way you would compute a mixture-and-ratio problem in your math textbook. Suppose a container is exactly 900px wide (imagine its border and padding are zero, so this is the space available to the columns) and you write:
.layout {
display: grid;
grid-template-columns: 200px 1fr 2fr;
}
Step 1: The fixed column takes 200px off the top. Space remaining = 900 − 200 = 700px.
Step 2: There is no gap declared, so nothing more is subtracted.
Step 3: The two flexible columns are marked 1fr and 2fr — three "shares" in total (1 + 2 = 3). Each share is worth 700 ÷ 3 ≈ 233.33px.
Step 4: The 1fr column gets 1 share = 233.33px. The 2fr column gets 2 shares = 466.67px.
Check: 200 + 233.33 + 466.67 = 900px. Exactly the container width, as it must be.
Now let's add a gap, because gaps are where students most often get the arithmetic wrong — they forget the gap is subtracted before the fr division, not after.
.layout2 {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
width: 920px;
}
Three equal columns and a 920px-wide container. There are two gaps between three columns (one gap between column 1 and 2, another between column 2 and 3), so total gap width = 2 × 20 = 40px. Space remaining for the fr columns = 920 − 40 = 880px. Divided into 3 equal shares: 880 ÷ 3 ≈ 293.33px per column. Verify: (3 × 293.33) + 40 = 880 + 40 = 920px. That matches the container width, confirming the gap was correctly removed first.
This is precisely why CSS Grid was such a relief compared to older layout tricks: you state ratios and fixed sizes together in one line, and the browser recalculates this arithmetic automatically every time the container is resized — something you would otherwise have to redo by hand on a calculator every time.
Grid Lines: The Coordinate System Behind Every Cell
So far, items have been flowing into the grid automatically, one per cell, in order. But real layouts need control — you want the header to stretch across every column, and the footer to stretch across every column too, while the sidebar only occupies one narrow column down the side. To do this you place items explicitly, and to place an item explicitly you need to understand that CSS Grid numbers lines, not cells.
Picture the grid as a sheet of ruled graph paper. The columns and rows are the strips between the ruled lines, but the ruled lines themselves are what get numbered, starting from 1 at the top-left corner. If a grid has 3 columns, it has 4 vertical lines bounding them — line 1 before column 1, line 2 between columns 1 and 2, line 3 between columns 2 and 3, and line 4 after column 3. In general, a grid with n columns always has n + 1 column lines, and a grid with m rows has m + 1 row lines. This "off-by-one" is exactly the same idea as fence posts: 3 sections of fence need 4 posts.
You place an item by telling it which line to start at and which line to end at, using grid-column and grid-row:
.banner {
grid-column: 1 / 3; /* start at line 1, end at line 3 */
grid-row: 1 / 2; /* start at line 1, end at line 2 */
}
grid-column: 1 / 3 does not mean "columns 1 through 3." It means "start at line 1 and stretch to line 3," which covers columns 1 and 2 — two columns, because the item spans the space between line 1 and line 3, crossing over line 2 in the middle. Confusing the line numbers with column counts is the single most common mistake beginners make with Grid placement, so it is worth re-reading that sentence once more before moving on. If you only care about how many tracks to span rather than the exact line numbers, CSS also lets you write grid-column: span 2;, which means "span 2 columns starting from wherever this item would normally land."
The diagram below shows a 3-column, 3-row grid with its lines numbered, and three items placed by line number: a banner spanning the first two columns of row 1 (grid-column: 1 / 3; grid-row: 1 / 2;), a small widget sitting in just the third column of row 1 (grid-column: 3 / 4; grid-row: 1 / 2;), and a footer spanning all three columns of row 3 (grid-column: 1 / 4; grid-row: 3 / 4;), with row 2 left as empty content cells.
Naming Regions With grid-template-areas
Counting line numbers works, but for a whole-page layout there is a more readable way to describe the same structure: give each region a name and draw the layout as a small text picture. This is one of CSS Grid's most distinctive features — nothing else in CSS lets you sketch a page layout directly inside your stylesheet.
.page {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 80px 1fr 60px;
gap: 10px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
Read the grid-template-areas value the way you would read a seating plan drawn on paper: each quoted line is one row of the grid, and each word inside it is the name of the region that occupies that cell. Because "header header" repeats the word header across both column positions in row 1, the header stretches across the full width, exactly like the top banner of the IRCTC page. Row 2 has two different names side by side — sidebar in the narrow 200px column and main in the flexible remaining column — so those two elements sit next to each other. Row 3 repeats footer across both columns, just like the header did. Every named region has to form a rectangle for this to work; you cannot write an L-shaped region.
Once the areas are named in the container, each child only needs one line — grid-area: header; — to know exactly where it belongs, without a single line number in sight. This is usually the easiest way to lay out a full page, while the line-number method from the previous section is better for placing individual items inside a smaller grid, like a photo gallery or a calendar.
repeat(): Avoiding Repetition for Galleries
Writing 1fr 1fr 1fr 1fr 1fr 1fr for a six-column gallery of, say, badge images from a school science exhibition is tedious and easy to miscount. CSS Grid provides a function, repeat(), that takes a count and a track size and expands to exactly that pattern:
.exhibition-gallery {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 12px;
}
repeat(6, 1fr) is exactly equivalent to writing 1fr six times — the browser expands it before doing any of the sizing arithmetic from earlier in this chapter. You can mix a repeated pattern with fixed tracks too, for example grid-template-columns: 220px repeat(4, 1fr); for a fixed sidebar next to four equal flexible columns.
A more advanced pattern worth knowing about, since you will meet it in real websites, replaces the fixed count with the keyword auto-fit and wraps the track size in minmax(): grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));. This tells the browser "fit as many 150px-or-wider columns as will comfortably fit in the available width, and stretch them evenly to fill any leftover space" — which is how a gallery automatically shows more columns on a laptop screen and fewer on a phone screen, without a single media query. You do not need to master the details of this yet; just recognise it as repeat() and fr, the two ideas you already understand, combined for a responsive layout.
A Common Misconception, Corrected
The mistake students make most often with CSS Grid is treating fr as if it behaved like a percentage of the whole container — believing, for instance, that in grid-template-columns: 1fr 1fr; each column is exactly "50% of the container." This is only true when there is no gap and no fixed-size sibling column. As soon as you add gap: 20px;, each column becomes slightly less than half the container, because the gap is real space that has to come from somewhere, and it is subtracted before the fr division happens — exactly as computed step by step earlier in this chapter. If you ever need a column to be exactly a fixed percentage regardless of gaps, use an explicit percentage value like 50% instead of 1fr.
A second, smaller misconception is worth naming too: CSS Grid is not the same thing as an HTML <table>, even though a simple grid can look identical to a table on screen. A <table> is a semantic HTML element meant for genuinely tabular data — like a CBSE marksheet with subject names down one side and exam attempts across the top, where screen readers and search engines understand the row/column relationship as data. CSS Grid, on the other hand, is purely a visual layout tool applied to ordinary elements like <div>; it carries no meaning about the content being tabular data at all. Use <table> when the content genuinely is a table (like exam results); use CSS Grid when you are arranging page sections, cards, or images that happen to look grid-like but are not data.
Active Recall: Test Yourself
- A container is 1000px wide, with no gap. Its CSS is
grid-template-columns: 300px 1fr 1fr;. Compute the width of each of the two flexible columns. (Work: 1000 − 300 = 700 free space; 700 ÷ 2 = 350px each.) - The same container now adds
gap: 10px;. Recompute the width of the two flexible columns, remembering there are two gaps between three columns. (Work: two gaps = 20px; 1000 − 300 − 20 = 680 free space; 680 ÷ 2 = 340px each.) - A grid has 5 columns of equal width. How many vertical grid lines does it have, and what are their numbers? (Answer: 6 lines, numbered 1 to 6, because n columns always produce n + 1 lines.)
- An item is placed with
grid-column: 2 / 5;. How many columns does it actually span, and which ones? (Answer: 3 columns — columns 2, 3, and 4 — because the item stretches from line 2 to line 5, crossing lines 3 and 4 in between.) - Write the single-line shorthand equivalent of writing out
1fr 1fr 1fr 1frby hand for a 4-column grid. (Answer:repeat(4, 1fr).) - In a
grid-template-areaslayout, why must every named region be a rectangle? What would happen if you tried to make an L-shaped "sidebar" area by placing the name in a non-rectangular pattern of quoted rows? (Answer: the CSS becomes invalid and the browser ignores thatgrid-template-areasdeclaration entirely, because grid areas can only be described as rectangular blocks of a repeated name.)
Summary
CSS Grid turns a container into a two-dimensional coordinate system of rows and columns, switched on with display: grid; and sized with grid-template-columns and grid-template-rows. Track sizes can be fixed (200px), or flexible using the fr unit, which always divides only the space left over after fixed tracks and gap values have already been subtracted — never a straight percentage of the whole container. Items can be placed automatically in reading order, or explicitly using grid line numbers with grid-column and grid-row, remembering that an n-track grid always has n + 1 lines and that a span like 1 / 3 describes a range of lines, not a count of columns. For whole-page layouts, grid-template-areas lets you sketch the layout as a readable text diagram, with every named region required to form a rectangle. repeat() shortens repetitive track lists, and combined with minmax() and auto-fit it can build layouts that reflow responsively without media queries. Keep the fr-vs-percentage distinction and the grid-vs-table distinction firmly in mind, since these are the two ideas beginners most often get backwards.
Practice Exercises
Now it is time to practice! Complete these challenges to solidify your understanding:
- Exercise 1: Write a short program that demonstrates the core concept from this chapter. Test it with at least 3 different inputs.
- Exercise 2: Find a real-world example where css grid is used in an Indian company (like TCS, Infosys, Flipkart, or ISRO). Write a paragraph explaining the connection.
- Exercise 3: Create a mind-map connecting css grid to at least 3 other topics you have studied.