Skip to main content
CSS 7 mins read Devs2.org

CSS Grid Complete Guide - Master Two-Dimensional Layouts

Learn CSS Grid from the ground up. Discover how to create powerful two-dimensional layouts with Grid. Master rows, columns, areas, and responsive design patterns. Perfect for developers ready to level up their CSS skills.

#CSS #CSS Grid #Web Development #Layout #Frontend #Responsive Design

CSS Grid Layout is one of the most powerful tools in modern web development. While Flexbox revolutionised one-dimensional layouts, Grid brings the same level of control and flexibility to two-dimensional layouts—letting you arrange elements in rows and columns simultaneously. css-grid-complete-guide

If you’ve ever struggled with complex page layouts, uneven column heights, or wrestling CSS into submission for a dashboard or magazine-style design, Grid is the solution you’ve been waiting for. It turns layout tasks from frustrating hacks into clean, intuitive code.

In this guide, you’ll learn everything you need to use CSS Grid effectively—from the basics of creating a grid to advanced techniques like auto-fit, named areas, and responsive patterns that work without a single media query.

What is CSS Grid?

CSS Grid is a two-dimensional layout system that gives you complete control over both rows and columns. Think of it as placing items on a spreadsheet: you define the rows and columns, then position items wherever you want in that grid.

What Grid excels at:

  • Full-page layouts with headers, sidebars, and footers
  • Card grids that automatically reflow
  • Magazine-style layouts with overlapping elements
  • Dashboard designs with complex multi-column arrangements
  • Forms with precise alignment across rows and columns

Grid vs Flexbox: When to Use Which

Grid and Flexbox aren’t competitors—they’re complementary tools:

Use CaseBest Tool
Full page layoutCSS Grid
Navigation barFlexbox
Card gridCSS Grid or Flexbox
Centering a buttonFlexbox
Dashboard layoutCSS Grid
Form alignmentCSS Grid
Component interiorFlexbox

Rule of thumb: Use Grid for the big picture (page layout), and Flexbox for the details (component alignment).

Getting Started with CSS Grid

Everything in Grid starts with one line of CSS:

.container {
  display: grid;
}

That alone doesn’t do much visible work—you need to define your rows and columns. Let’s build a simple grid step by step.

Defining Columns with grid-template-columns

The most common starting point is defining how many columns you want and their sizes:

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
}

This creates three columns: 200px wide, then two flexible columns that share the remaining space. The 1fr unit is a grid-specific fractional unit—it divides unused space proportionally.

Try this HTML with the CSS above:

<div class="container">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
</div>

Items 1, 2, and 3 go in the first row. Items 4, 5, and 6 wrap to the second row. Item 1 is 200px wide; items 2 and 3 share the remaining space evenly.

Defining Rows with grid-template-rows

You can also control row heights:

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  grid-template-rows: 100px auto 100px;
}

This creates three rows: a 100px header row, a flexible content row, and a 100px footer row.

The repeat() Function

When you have many columns of the same size, repeat() keeps your code clean:

/* Without repeat */
grid-template-columns: 1fr 1fr 1fr 1fr;

/* With repeat - much cleaner */
grid-template-columns: repeat(4, 1fr);

/* Three columns of different sizes, repeated pattern */
grid-template-columns: repeat(2, 1fr 2fr);
/* Same as: 1fr 2fr 1fr 2fr */

Gap Control

Spacing between grid items is simple with the gap property:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;          /* Both row and column gaps */
  /* or separately: */
  row-gap: 16px;
  column-gap: 24px;
}

This replaces the old hack of using margins and negative margins on individual items—a huge quality-of-life improvement.

Placing Items on the Grid

By default, items flow into grid cells in document order (left to right, top to bottom). But Grid’s real power comes from placing items exactly where you want them.

Line-Based Placement

Grid lines are numbered starting from 1 at the top-left:

.header {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 2;
}

The shorthand version is cleaner:

.header {
  grid-column: 1 / 4;  /* Start at line 1, end at line 4 */
  grid-row: 1 / 2;     /* First row only */
}

.sidebar {
  grid-column: 1 / 2;  /* First column */
  grid-row: 2 / 4;     /* Rows 2 and 3 */
}

.content {
  grid-column: 2 / 4;  /* Columns 2 and 3 */
  grid-row: 2 / 3;     /* Row 2 only */
}

.footer {
  grid-column: 1 / 4;  /* Full width */
  grid-row: 3 / 4;     /* Last row */
}

With this HTML:

<div class="container">
  <header class="header">Header</header>
  <aside class="sidebar">Sidebar</aside>
  <main class="content">Content</main>
  <footer class="footer">Footer</footer>
</div>

You get a classic Holy Grail layout with just CSS Grid—no floats, no hacks.

Using the span Keyword

Instead of specifying end lines, you can use span to say how many cells an item should cover:

.header {
  grid-column: 1 / span 3;  /* Span 3 columns starting from 1 */
}

.sidebar {
  grid-row: 2 / span 2;     /* Span 2 rows from row 2 */
}

Named Grid Areas

For complex layouts, named areas make your CSS incredibly readable:

.container {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar content"
    "footer  footer";
  min-height: 100vh;
  gap: 16px;
}

header { grid-area: header; }
aside  { grid-area: sidebar; }
main   { grid-area: content; }
footer { grid-area: footer; }

The ASCII-art style of grid-template-areas makes the layout immediately understandable. Each string is a row, and each value in the row maps to a column. Use a period (.) to leave a cell empty.

/* Magazine layout with empty cells */
grid-template-areas:
  "header  header  header"
  "sidebar .       content"
  "footer  footer  footer";

The minmax() Function

minmax() sets minimum and maximum sizes for tracks, enabling responsive layouts without media queries:

.container {
  display: grid;
  grid-template-columns: repeat(3, minmax(200px, 1fr));
}

Each column has a minimum width of 200px and can grow up to 1fr (one fraction of available space). This prevents columns from shrinking too small while still being flexible.

Auto-Fit and Auto-Fill

These are game-changers for responsive grids:

/* Cards that automatically wrap to new rows */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 24px;
}

What this does:

  • Each card has a minimum width of 250px
  • Cards grow to fill available space (1fr)
  • When the container shrinks and cards would go below 250px, they wrap to a new row
  • Result: a responsive card grid with zero media queries

The difference between auto-fit and auto-fill:

  • auto-fill: keeps empty tracks (maintains column structure even when empty)
  • auto-fit: collapses empty tracks (columns stretch to fill space)
/* auto-fill: keeps empty columns (great for consistent grid structure) */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

/* auto-fit: collapses empty columns (cards expand to fill space) */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

Placing Items Explicitly

You can place items wherever you want, even out of order:

.item-1 { grid-column: 3; grid-row: 1; }  /* Top-right */
.item-2 { grid-column: 1; grid-row: 3; }  /* Bottom-left */
.item-3 { grid-column: 2 / 4; grid-row: 2; }

This allows completely independent placement—the item’s position in the HTML doesn’t matter. Perfect for rearranging layouts on different screen sizes.

Grid Auto Flow

Controls how items that aren’t explicitly placed are handled:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-auto-flow: row;  /* Default: fill rows first */
}

/* Fill columns first instead */
.container {
  grid-auto-flow: column;
}

/* Dense packing fills gaps automatically */
.container {
  grid-auto-flow: row dense;
}

The dense keyword is particularly useful—it backfills gaps with smaller items, giving you a Pinterest-style masonry-like layout.

Real-World Layout: Full Page Dashboard

Let’s build a complete dashboard layout:

.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr 300px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "sidebar  header  header"
    "sidebar  main    aside"
    "sidebar  footer  footer";
  min-height: 100vh;
  gap: 0;
}

.dashboard-header { grid-area: header; }
.dashboard-sidebar { grid-area: sidebar; }
.dashboard-main { grid-area: main; }
.dashboard-aside { grid-area: aside; }
.dashboard-footer { grid-area: footer; }
<div class="dashboard">
  <header class="dashboard-header">
    <h1>Dashboard</h1>
    <input type="search" placeholder="Search...">
  </header>
  <nav class="dashboard-sidebar">
    <ul>
      <li>Overview</li>
      <li>Analytics</li>
      <li>Settings</li>
    </ul>
  </nav>
  <main class="dashboard-main">
    <div class="stats-grid">
      <!-- Cards -->
    </div>
  </main>
  <aside class="dashboard-aside">
    <h3>Recent Activity</h3>
    <!-- Activity feed -->
  </aside>
  <footer class="dashboard-footer">
    <p>&copy; 2026 Dashboard</p>
  </footer>
</div>

A common pattern—a gallery that adapts from 1 column to 4+ columns:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
  padding: 16px;
}

.gallery-item {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.gallery-item.featured {
  grid-column: span 2;
  grid-row: span 2;
}

With just auto-fit and minmax, this gallery works on any screen—from mobile (1 column) to desktop (4+ columns)—without a single breakpoint. Use the featured class to make important items span multiple cells.

Real-World Layout: Holy Grail (Responsive)

The classic Holy Grail layout, made responsive with one media query:

body {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "nav     main    aside"
    "footer  footer  footer";
  min-height: 100vh;
  margin: 0;
  gap: 0;
}

@media (max-width: 768px) {
  body {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "nav"
      "main"
      "aside"
      "footer";
  }
}

header { grid-area: header; background: #333; color: white; padding: 1rem; }
nav    { grid-area: nav; background: #f0f0f0; padding: 1rem; }
main   { grid-area: main; padding: 1rem; }
aside  { grid-area: aside; background: #f0f0f0; padding: 1rem; }
footer { grid-area: footer; background: #333; color: white; padding: 1rem; }

On large screens: three columns with sidebar and aside. On mobile: everything stacks vertically. One media query, and the grid-template-areas change does all the work.

Advanced: Overlapping Items

Grid items can overlap—unlike Flexbox items. This enables creative designs:

.hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.hero-image {
  grid-column: 1 / 3;
  grid-row: 1;
  width: 100%;
  height: 400px;
  object-fit: cover;
}

.hero-text {
  grid-column: 2 / 3;
  grid-row: 1;
  align-self: center;
  justify-self: center;
  background: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 2rem;
  z-index: 1;
}

The text box overlaps the image, positioned on the right side. The z-index controls which element sits on top.

Combining Grid with Flexbox

The best layouts use both Grid and Flexbox together:

.page {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas: "nav content";
  min-height: 100vh;
}

nav {
  grid-area: nav;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 1rem;
}

.content {
  grid-area: content;
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 1 1 280px;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

Grid controls the big picture (sidebar + content area). Flexbox handles the internal arrangement of nav links and cards.

Responsive Strategy Without Media Queries

CSS Grid can handle many responsive patterns without any breakpoints at all:

/* Auto-sizing cards */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(clamp(250px, 30vw, 400px), 1fr));
  gap: 24px;
}

This single line creates a card layout that:

  • Shows 1 column on narrow phones
  • Shows 2 columns on tablets
  • Shows 3+ columns on desktops
  • All without a single @media rule

For forms and data display, you can use the same technique:

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
}

Each form field pair (label + input) gets a minimum of 300px, wrapping gracefully on smaller screens.

CSS Grid Properties Cheat Sheet

Container Properties

PropertyValuesDescription
displaygrid / inline-gridCreates a grid container
grid-template-columnslengths, %, fr, repeat(), minmax()Defines columns
grid-template-rowslengths, %, fr, repeat(), minmax()Defines rows
grid-template-areasnamed area stringsNames grid areas
gaplengthSpace between items
justify-itemsstart / end / center / stretchAligns items horizontally in cells
align-itemsstart / end / center / stretchAligns items vertically in cells
grid-auto-flowrow / column / denseControls auto-placement behavior

Item Properties

PropertyValuesDescription
grid-columnstart / end or span NItem’s column placement
grid-rowstart / end or span NItem’s row placement
grid-areaname or start/end rows+columnsItem’s named area or combined placement
justify-selfstart / end / center / stretchOverrides justify-items for this item
align-selfstart / end / center / stretchOverrides align-items for this item

Next Steps

CSS Grid transforms how you think about layout. Start by recreating a simple page layout (header, sidebar, content, footer) with named grid areas. Then experiment with auto-fit and minmax for responsive card layouts. Once you’re comfortable, try overlapping elements and dashboard designs.

For quick JSON formatting of your grid data or configuration files, try the JSON formatter on Devs2.org. And if you need to indent or beautify your CSS code, the text beautifier can help keep your stylesheets clean and readable.

Conclusion

CSS Grid is not just another layout tool—it’s a paradigm shift in how we think about web layouts. It turns complex, multi-column designs into clean, readable, and maintainable CSS. Combined with Flexbox for component-level work, Grid gives you everything you need to create any layout you can imagine.

The responsive patterns alone (auto-fit, minmax, named areas) save countless hours of media query writing and debugging. Whether you’re building a simple blog, a complex dashboard, or a magazine-style landing page, CSS Grid is the foundation you’ve been looking for.

Start using Grid today. Your future self will thank you when you need to rearrange a layout and all you have to do is change a few lines in grid-template-areas.

Recently Used Tools