March 26, 20265 min read

CSS Grid: The Layout System You Should Actually Be Using

A practical guide to CSS Grid covering grid-template-columns, fr units, grid areas, auto-fit/auto-fill, and building responsive layouts without media queries.

css css-grid layout frontend responsive-design
Ad 336x280

Flexbox gets all the attention, but CSS Grid is what you actually want for page-level layouts. Flexbox is great for one-dimensional stuff -- a row of buttons, a navbar, centering something. Grid handles two-dimensional layouts: rows AND columns at the same time. Most real interfaces need both, and knowing when to reach for which one makes your CSS dramatically simpler.

The Basics

Turn any element into a grid container:

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  gap: 16px;
}

That gives you a three-column layout where the sidebars are 200px and the center takes up whatever space is left. The gap property adds spacing between grid items (no more margin hacks).

The fr Unit

fr stands for "fraction of available space." It's the unit you'll use most with Grid.
grid-template-columns: 1fr 2fr 1fr;

This divides the available width into 4 parts: 1 for the first column, 2 for the middle, 1 for the last. The browser handles the math. You don't need to think in percentages or calc().

You can mix fr with fixed units:

grid-template-columns: 250px 1fr;

Sidebar is always 250px. Main content gets everything else. This is the holy grail layout in two lines of CSS.

Placing Items on the Grid

By default, items flow into the grid left-to-right, top-to-bottom. But you can place them explicitly:

.header  { grid-column: 1 / -1; }    / Span all columns /
.sidebar { grid-column: 1; grid-row: 2; }
.main    { grid-column: 2; grid-row: 2; }
.footer  { grid-column: 1 / -1; }

The 1 / -1 syntax means "from the first grid line to the last." Grid lines are numbered starting at 1 (not 0 -- CSS isn't JavaScript).

Named Grid Areas (the Good Stuff)

This is where Grid gets really expressive. Instead of juggling line numbers, you can name areas and lay them out visually:

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

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

Read that grid-template-areas block. It literally looks like the layout. That's the whole point -- you can see the structure at a glance.

Want to change the layout for mobile? Just redefine the areas:

@media (max-width: 768px) {
  .container {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "footer";
  }
}

Same HTML, completely different layout. Two declarations changed.

Responsive Grids Without Media Queries

Here's the trick that makes Grid incredible for card layouts:

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

Break that down:

  • repeat() -- repeat a column pattern
  • auto-fill -- create as many columns as will fit
  • minmax(280px, 1fr) -- each column is at least 280px, but grows to fill space
This creates a responsive grid that goes from 4 columns to 3 to 2 to 1 as the viewport shrinks. Zero media queries. The browser figures it out.

auto-fill vs auto-fit

These are almost identical, with one difference:

  • auto-fill creates empty tracks if there's extra space
  • auto-fit collapses empty tracks so items stretch to fill
With 3 items and space for 5 columns:
  • auto-fill gives you 3 items and 2 empty column slots
  • auto-fit gives you 3 items that stretch wider to fill the row
Most of the time you want auto-fill. Use auto-fit when you have very few items and want them to stretch.

Grid vs Flexbox: When to Use Which

Use Grid when:
  • You need to control both rows and columns
  • You're building a page-level layout
  • You want items to align in a strict grid (like a card layout or dashboard)
  • You're doing anything that looks like a table but isn't tabular data
Use Flexbox when:
  • You're arranging items in a single row or column
  • You need items to wrap naturally without strict column alignment
  • You're building component-level layouts (a button with an icon, a nav bar)
  • You need items to grow/shrink based on content
In practice, you'll nest them. Grid for the page layout, Flexbox inside individual components. They complement each other.

Real Example: Dashboard Layout

.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr;
  grid-template-areas:
    "nav header"
    "nav content";
  height: 100vh;
}

.nav { grid-area: nav; }
.header { grid-area: header; }
.content { grid-area: content; overflow: auto; }

/ Cards inside the content area /
.content-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}

That's a full dashboard shell -- fixed sidebar, header bar, scrollable content area with a responsive card grid inside. About 20 lines of CSS.

Gotchas

Grid items stretch by default. Child elements fill their grid cell both horizontally and vertically. Use align-self and justify-self to control this, or place-items on the container. Percentage heights can be weird. If your grid container doesn't have an explicit height, percentage-based row sizing might not work as expected. Use fr or auto instead. Subgrid support is still limited. grid-template-columns: subgrid lets nested grids align to the parent grid. It's in Firefox and Safari but Chrome only added it recently. Check caniuse before relying on it.

Practice It

Grid is one of those things that clicks way faster when you're actually writing and tweaking code than when you're just reading about it. If you want to experiment with Grid layouts in real time, CodeUp has an interactive environment where you can see your changes rendered instantly -- no local setup needed.

The syntax feels verbose at first, but Grid replaces entire frameworks worth of layout code. Once you internalize grid-template-columns, fr, and grid-template-areas, you'll look at your old float-based and flexbox-hacked layouts and wonder how you ever put up with them.

Ad 728x90