A few years ago, I sat down to build a dashboard. Nothing fancy—just a fixed sidebar, a main content area, and a footer. Flexbox felt like the obvious choice, and at first, it behaved. Then I dropped a row of cards into the main section. The entire layout buckled. I spent the next three hours fighting with flex-grow ratios and nested percentage widths, watching containers refuse to line up no matter how much padding I subtracted. The page felt like a tower about to fall.

That bruising experience taught me the single most important thing about modern CSS layout: Flexbox and Grid are not rivals. They are tools for different jobs, and most failed layouts come from grabbing the wrong one.

The Difference Is Dimensional

Think of Flexbox as a hallway. Items flow in one direction, either as a row or as a column. It is built for one-dimensional distribution. The browser looks at the content, then decides how to stretch, shrink, or align it along that single axis. This makes Flexbox perfect for situations where content dictates the layout. A navigation bar, a stack of form fields, or a set of tags that need equal spacing all sit naturally in a flex container because they share one line of logic.

Grid, on the other hand, is a floor plan. It is strictly two-dimensional, handling rows and columns at the same time. You define the structure first, then you place items inside it. This makes Grid ideal for overall page architecture—anywhere you need to control vertical and horizontal positioning together. When you try to force a complex two-dimensional design through nested Flexbox containers, you end up with deep markup, fragile wrappers, and brittle math that falls apart the moment you add one extra element.

Flexbox Still Earns Its Keep

Do not rush to replace every flex container with Grid. Inside individual components, Flexbox is often cleaner and more honest. If you have a card footer with two buttons and you want one aligned to the left and one to the right, justify-content: space-between does exactly what you mean. If you need to vertically center an icon inside a button of unknown height, align-items: center is the simplest path. Variable content—like a row of user badges with different name lengths—fits comfortably inside Flexbox because it is content-first. The container adapts to what it holds.

Grid is container-first. You tell the browser how many tracks exist and how large they should be, then you drop items into those cells. If your layout is really just a single line of siblings sharing space, Grid adds unnecessary ceremony.

Page Layout Belongs to Grid

This is where Grid takes over. Remember my dashboard nightmare? Here is how the structure should have looked from the start:

.page {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 200px 1fr;
}

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

Look at what is happening. The .page container establishes three rows and two columns. The first row sizes itself to whatever the header contains thanks to auto. The middle row claims all available leftover space with 1fr. The footer lands in the final row, sized to its own content. Meanwhile, the sidebar locks to 200 pixels wide, and the main area fills the rest.

The placement logic is the real relief. The header spans from column line 1 to line -1, which means it stretches across both columns regardless of how many columns you add later. The sidebar and main content share row 2 but occupy separate columns. The footer returns to full width in row 3. You do not need percentage math on the children. You do not need nested wrappers fighting over height. Change the sidebar width in one place, and the main area adjusts automatically. The entire layout breathes as a single system.

Readability With grid-template-areas

For even more clarity, you can name your sections. Instead of managing line numbers, you write a visual map:

.page {
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

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

Now your stylesheet reads like a wireframe. If you ever want the sidebar to appear on the right for a different breakpoint, you swap two words in the template string. That kind of structural readability is impossible to achieve inside a tower of nested flex containers.

Two Hard Lessons

Grid is not magic. There are two mistakes that will wreck your layout quickly.

Het eerste is slordig gebruik van eenheden. Als je grid-template-columns: 1fr 1fr 1fr definieert, maar je ontwerp slechts twee kolommen met inhoud nodig heeft, dan bestaat die derde track nog steeds. Deze blijft ofwel leeg achter en creëert een onverwachte opening, of het dwingt je werkelijke inhoud om op een manier te worden samengeperst die je ontwerp verpest. Wees doelbewust. Als je twee kolommen bedoelt, schrijf dan repeat(2, 1fr).