What Is CSS Grid and Why It Changed Everything
CSS Grid is a two-dimensional layout system that gives you simultaneous control over columns and rows. Before Grid, developers relied on floats, tables, inline-block hacks, and Flexbox to build page layouts. Each of these approaches was either one-dimensional (Flexbox) or never designed for layout at all (floats and tables). CSS Grid was the first layout method purpose-built for the task.
With a single display: grid declaration on a container, every direct child becomes a grid item that you can place into any cell, span across multiple columns or rows, and align along both axes. No wrapper divs. No clearfix hacks. No JavaScript layout libraries.
Every modern browser supports CSS Grid. According to Can I Use, global support is above 97%. There is no reason to avoid it in production. If you are still using float-based grids or a CSS framework purely for its grid system, CSS Grid is the native replacement you have been waiting for.
To experiment with Grid properties in real time, try the NexTool CSS Grid Playground. It lets you adjust columns, rows, gap, and alignment visually and see the generated CSS instantly.
CSS Grid is two-dimensional. It controls columns and rows at the same time. This is the fundamental difference between Grid and Flexbox, which handles only one direction at a time.
grid-template-columns and grid-template-rows
The two most important Grid properties define the structure of your grid: how many columns it has, how many rows, and how wide or tall each track is.
Defining Columns
grid-template-columns accepts a space-separated list of track sizes. Each value defines one column.
.container {
display: grid;
grid-template-columns: 200px 400px 200px;
}
This creates three columns: 200px, 400px, and 200px. The total width is fixed at 800px. For responsive layouts, you will rarely use all fixed values. Instead, combine fixed widths with flexible units.
/* Three equal columns using percentages */
grid-template-columns: 33.33% 33.33% 33.33%;
/* Shorthand with repeat() */
grid-template-columns: repeat(3, 1fr);
/* Sidebar + main content */
grid-template-columns: 280px 1fr;
/* Holy grail: sidebar - main - sidebar */
grid-template-columns: 250px 1fr 250px;
Defining Rows
grid-template-rows works identically but for the vertical axis. In practice, you define rows less often because Grid creates implicit rows automatically when content overflows the explicit grid.
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 80px 1fr 60px; /* header, main, footer */
}
If you have six items in a two-column grid but only defined three rows, Grid creates additional rows as needed. Control the size of these implicit rows with grid-auto-rows:
grid-auto-rows: minmax(100px, auto);
This ensures every auto-created row is at least 100px tall but can grow to fit its content. Use the NexTool CSS Grid Generator to visually configure your column and row definitions and export clean CSS.
The fr Unit: Fractional Space Distribution
The fr unit is the most powerful sizing tool in CSS Grid. It stands for "fraction of the remaining space" and distributes available space proportionally after fixed-size tracks are accounted for.
/* Two equal columns */
grid-template-columns: 1fr 1fr;
/* Second column is twice as wide */
grid-template-columns: 1fr 2fr;
/* Fixed sidebar + fluid main */
grid-template-columns: 300px 1fr;
/* Three columns: fixed, fluid, fixed */
grid-template-columns: 200px 1fr 200px;
In the last example, the browser first allocates 200px to the first column and 200px to the third. Whatever space remains goes to the middle column. If the container is 1000px wide, the middle column gets 600px. If the container is 800px, the middle column gets 400px. The fr unit makes this calculation automatic.
Why not percentages? The fr unit is smarter than percentages because it accounts for gaps. If you use grid-template-columns: 50% 50% with a gap: 20px, the total exceeds 100% and causes overflow. With 1fr 1fr, the browser subtracts the gap first, then distributes the remaining space. No overflow, no math required.
The gap Property
The gap property sets the spacing between grid tracks. It replaces the old grid-gap property (which still works as an alias but is no longer necessary).
/* Equal gap on all sides */
gap: 20px;
/* Different row and column gaps */
gap: 20px 40px; /* row-gap column-gap */
/* Individual properties */
row-gap: 20px;
column-gap: 40px;
The gap only applies between grid items, not around the outer edges of the grid. This is a major advantage over using margins, where you would need to handle edge cases for the first and last items in each row. With gap, there are no edge cases. The browser handles it automatically.
auto-fit and auto-fill: Responsive Grids Without Media Queries
The repeat() function accepts two special keywords -- auto-fit and auto-fill -- that make grids responsive without a single media query.
/* The responsive grid pattern */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
This single line does the following: create as many columns as will fit in the container, where each column is at least 280px wide and expands equally to fill any remaining space. On a 1200px screen, you get four columns. On a 600px screen, you get two. On a 300px screen, you get one. The browser recalculates automatically.
auto-fit vs auto-fill
The difference matters when there are fewer items than available columns:
- auto-fill creates empty tracks to fill the container. The items do not stretch beyond their minimum size.
- auto-fit collapses empty tracks to zero width, allowing the existing items to stretch and fill the container.
/* auto-fill: keeps empty columns */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* auto-fit: collapses empty columns, items stretch */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
In most cases, auto-fit is what you want. It produces a cleaner result when the number of items is variable. Use auto-fill when you need items to maintain a consistent maximum width regardless of how few there are.
The pattern repeat(auto-fit, minmax(280px, 1fr)) is the most useful single line in CSS Grid. It creates a fully responsive grid that works for card layouts, image galleries, feature grids, and product listings. Adjust the 280px minimum to your content's ideal width.
Named Grid Areas: Readable Layouts
Named grid areas let you describe your layout in a visual, almost ASCII-art syntax. Instead of placing items by line numbers, you assign names to regions and reference those names in your CSS.
.container {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 0;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
The grid-template-areas property uses one string per row. Each word in the string names a cell. Repeating a name across adjacent cells causes that area to span multiple columns or rows. The visual structure of the strings mirrors the visual structure of the page, making the layout immediately understandable.
Responsive Layouts with Named Areas
Named areas become even more powerful with media queries. You can completely rearrange the layout by redefining the area strings:
/* Mobile: single column stack */
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}
The HTML stays identical. Only the CSS changes. The sidebar moves below the main content on mobile. The header and footer span the full width on both layouts. This separation of structure (HTML) and presentation (CSS) is exactly what Grid was designed for.
Use a period (.) to create an empty cell in the grid:
grid-template-areas:
"header header header"
"sidebar main ."
"footer footer footer";
Alignment: Positioning Items Within the Grid
CSS Grid provides six alignment properties that control how items are placed within their cells and how the grid itself is positioned within its container.
Aligning Items (Within Their Cells)
/* Horizontal alignment of all items within their cells */
justify-items: start | center | end | stretch;
/* Vertical alignment of all items within their cells */
align-items: start | center | end | stretch;
/* Shorthand for both */
place-items: center center;
To align a single item differently from the others, use the item-level properties on that specific child:
.special-item {
justify-self: end; /* horizontal */
align-self: center; /* vertical */
place-self: center end; /* shorthand */
}
Aligning the Grid (Within Its Container)
When the total size of your grid tracks is smaller than the container, you can position the entire grid within the container:
/* Horizontal positioning of the entire grid */
justify-content: start | center | end | space-between | space-around | space-evenly;
/* Vertical positioning of the entire grid */
align-content: start | center | end | space-between | space-around | space-evenly;
/* Shorthand */
place-content: center center;
The space-between, space-around, and space-evenly values distribute extra space between or around the grid tracks, similar to how Flexbox distributes space along its main axis. To experiment with all alignment options visually, open the CSS Grid Playground and toggle each property in real time.
Responsive CSS Grid Patterns You Can Copy
These are production-ready patterns that solve common layout problems. Copy the CSS, adjust the values to your content, and you are done.
1. Responsive Card Grid
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
Works for blog cards, product listings, team member profiles, and feature sections. No media queries needed. Adjust the 300px minimum to your card's optimal reading width.
2. Sidebar Layout
.page-layout {
display: grid;
grid-template-columns: 280px 1fr;
gap: 32px;
min-height: 100vh;
}
@media (max-width: 768px) {
.page-layout {
grid-template-columns: 1fr;
}
}
The sidebar is a fixed 280px on desktop and collapses to full-width on mobile. The main content fills the remaining space.
3. Holy Grail Layout
.holy-grail {
display: grid;
grid-template:
"header header header" 80px
"nav content aside" 1fr
"footer footer footer" 60px
/ 200px 1fr 200px;
min-height: 100vh;
gap: 0;
}
@media (max-width: 768px) {
.holy-grail {
grid-template:
"header" auto
"nav" auto
"content" 1fr
"aside" auto
"footer" auto
/ 1fr;
}
}
The classic five-region layout (header, left nav, main content, right aside, footer) in pure CSS. The grid-template shorthand defines areas, row sizes, and column sizes in a single declaration.
4. Masonry-Style Staggered Grid
.staggered {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.staggered .tall {
grid-row: span 2;
}
.staggered .wide {
grid-column: span 2;
}
Items can span multiple rows or columns with grid-row: span N and grid-column: span N. This creates a Pinterest-style staggered layout. For a true masonry layout (where items pack tightly without gaps), the CSS masonry value for grid-template-rows is in development but not yet widely supported.
5. Auto-Sizing Dashboard
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(180px, auto);
gap: 20px;
}
.widget-large { grid-column: span 2; grid-row: span 2; }
.widget-wide { grid-column: span 2; }
.widget-tall { grid-row: span 2; }
A four-column dashboard where widgets can span multiple cells. The grid-auto-rows: minmax(180px, auto) ensures a minimum height while allowing content to grow. For generating the CSS for complex grid configurations, use the CSS Grid Generator.
Build Your Grid Visually
Drag, resize, and export production-ready CSS Grid code. No guesswork, no trial and error.
Open CSS Grid GeneratorCSS Grid vs Flexbox: When to Use Which
Grid and Flexbox are not competitors. They solve different problems and work best when used together.
Use CSS Grid when:
- You need to control both columns and rows (two-dimensional layout)
- You are building a full page layout with header, sidebar, content, and footer
- You need items to align in both directions simultaneously
- Your layout is defined by the container, not by the content
- You want to place items in specific grid cells regardless of source order
Use Flexbox when:
- You are laying out items in a single direction (one row or one column)
- You need content to determine the size of items (content-driven layout)
- You are building a navigation bar, button group, or card content area
- You want items to wrap naturally without defining explicit columns
The best approach is to use Grid for the outer page structure and Flexbox for the content inside each grid cell. A card grid uses display: grid on the container and display: flex; flex-direction: column inside each card to align the title, description, and button. Explore both systems side by side in the NexTool Flexbox Playground.
Grid for layout, Flexbox for content. Use Grid when you are dividing a page into regions. Use Flexbox when you are arranging elements within one of those regions. They are complementary, not competing.
Frequently Asked Questions
What is CSS Grid and when should I use it?
CSS Grid is a two-dimensional layout system built into CSS that lets you control columns and rows simultaneously. Use it when you need a full page layout, a card grid, a dashboard, or any design where elements must align along both axes. For single-axis layouts like a navigation bar, Flexbox is usually simpler.
What is the difference between CSS Grid and Flexbox?
Flexbox is one-dimensional: it handles layout in a single direction (row or column). CSS Grid is two-dimensional: it handles rows and columns at the same time. Use Flexbox for components like navbars and button groups. Use Grid for page-level layouts and any design where you need precise control over both axes. They work best together: Grid for the overall layout, Flexbox for content inside each cell.
What does the fr unit mean in CSS Grid?
The fr unit stands for "fraction of available space." It distributes remaining space proportionally after fixed sizes are subtracted. For example, grid-template-columns: 1fr 2fr creates two columns where the second is twice as wide. Unlike percentages, fr accounts for gaps automatically, so you never get overflow from combined widths exceeding 100%.
How do I make CSS Grid responsive without media queries?
Use grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)). This creates a grid that automatically adjusts the number of columns based on available space. Each column is at least 280px and expands equally to fill the container. No media queries needed because the browser recalculates as the viewport changes. Try it live in the CSS Grid Playground.
What are CSS Grid named areas and how do I use them?
Named areas let you assign names to grid regions and place elements by name instead of by line numbers. Define them with grid-template-areas using one string per row, like "header header" "sidebar main" "footer footer". Then assign elements with grid-area: header. This makes layouts readable and easy to rearrange with media queries.
Explore 150+ Free Developer Tools
CSS Grid tools are just the start. NexTool has free tools for Flexbox, colors, regex, JSON, encoding, hashing, and much more.
Browse All Free Tools