CSSFlexbox vs Grid — when to use each

Flexbox vs Grid — when to use each

Flexbox and CSS Grid are both layout tools, but they solve different problems. Flexbox excels at one-dimensional layouts (rows or columns), while Grid is powerful for two-dimensional layouts (rows AND columns). Understanding their strengths helps you choose the right tool for each layout challenge.

Key differences

Aspect

Flexbox

Grid

Dimensions

One-dimensional (row OR column)

Two-dimensional (row AND column)

Direction

Row or column, one axis

Both axes simultaneously

Items

Linear arrangement

Grid of cells

Best for

Navigation, toolbars, components

Page layouts, dashboards

Content

Content-based sizing by default

Container-based sizing

Alignment

main-axis & cross-axis

Rows and columns

CSS
<!-- Flexbox: one dimension at a time -->
.navbar {
  display: flex;
  gap: 20px;
  justify-content: space-between;
  align-items: center;
}

<!-- Controls horizontal arrangement -->
<!-- Vertical alignment is secondary (cross-axis) -->

.sidebar {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

<!-- Controls vertical arrangement -->
<!-- Horizontal alignment is secondary (cross-axis) -->

/* Grid: two dimensions together -->
.dashboard {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;  /* 3 columns -->
  grid-template-rows: auto 1fr auto;   /* 3 rows -->
  gap: 20px;
}

<!-- Controls BOTH columns and rows -->
<!-- Items placed in specific cells -->

/* Conceptual difference -->
.flex-row {
  display: flex;  /* items in a line -->
}

<!-- [Item] [Item] [Item] (all in one row) -->

.flex-column {
  display: flex;
  flex-direction: column;
}

<!-- [Item] -->
<!-- [Item] -->
<!-- [Item] (all in one column) -->

.grid-layout {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;  /* 3x3 grid -->
  grid-template-rows: 1fr 1fr 1fr;
}

<!-- [Item] [Item] [Item] -->
<!-- [Item] [Item] [Item] (items in cells) -->
<!-- [Item] [Item] [Item] -->
When to use Flexbox

CSS
<!-- Use flexbox for: -->

/* 1. Navigation and menus (horizontal layout) -->
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

<!-- Logo, nav items, buttons all in a row -->

/* 2. Toolbars and button groups -->
.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.button {
  flex: 0 0 auto;
}

<!-- Buttons arranged, wrap to new line if needed -->

/* 3. Cards and components -->
.card {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.card-header {
  flex: 0 0 auto;
}

.card-content {
  flex: 1;
}

.card-footer {
  flex: 0 0 auto;
}

<!-- Card structure: vertical arrangement -->

/* 4. Flexible spacing and alignment -->
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}

<!-- Content centered both ways -->

/* 5. Responsive wrapping -->
.gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.item {
  flex: 1 1 200px;
}

<!-- Items wrap naturally based on space -->

/* 6. Sidebar + content (two-column) -->
.layout {
  display: flex;
  gap: 20px;
}

.sidebar {
  flex: 0 0 250px;
}

.content {
  flex: 1;
}

<!-- Simple side-by-side layout -->
When to use Grid

CSS
<!-- Use grid for: -->

/* 1. Page layouts (header, sidebar, content, footer) -->
.page {
  display: grid;
  grid-template-columns: 1fr 4fr;
  grid-template-rows: auto 1fr auto;
  gap: 20px;
  min-height: 100vh;
}

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

<!-- Complex layout with multiple rows/columns -->

/* 2. Dashboards (many cells) -->
.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 20px;
}

.card {
  grid-column: span 1;  /* 1 cell wide -->
}

.feature {
  grid-column: span 2;  /* 2 cells wide -->
}

<!-- Widgets in specific grid positions -->

/* 3. Image grids and galleries -->
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.image {
  grid-column: auto;
}

.featured {
  grid-column: span 2;
}

<!-- Images in grid with some spanning -->

/* 4. Magazine-style layouts -->
.magazine {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
}

.article-main {
  grid-column: span 8;
}

.sidebar {
  grid-column: span 4;
}

<!-- Asymmetric layout -->

/* 5. Form layouts with aligned labels -->
.form {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
}

.label {
  grid-column: 1;
}

input {
  grid-column: 2;
}

<!-- Perfectly aligned columns -->

/* 6. Data tables and spreadsheets -->
.table {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
}

.cell {
  padding: 10px;
}

<!-- Uniform grid cells -->
Direct comparison: common layouts

CSS
<!-- Two-column layout -->

/* Flexbox approach -->
.flex-layout {
  display: flex;
  gap: 20px;
}

.flex-sidebar {
  flex: 0 0 250px;
}

.flex-content {
  flex: 1;
}

<!-- Simple and semantic -->

/* Grid approach -->
.grid-layout {
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 20px;
}

.grid-sidebar {
  grid-column: 1;
}

.grid-content {
  grid-column: 2;
}

<!-- More explicit but more code -->

/* Three-column layout -->

/* Flexbox with equal columns -->
.flex-three {
  display: flex;
  gap: 20px;
}

.flex-col {
  flex: 1 1 0;
}

<!-- Simple: flex: 1 makes equal -->

/* Grid with equal columns -->
.grid-three {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
}

<!-- Also clear: three equal 1fr columns -->

/* Navbar + main + footer -->

/* Flexbox vertical layout -->
.flex-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.flex-header {
  flex: 0 0 60px;
}

.flex-main {
  flex: 1;
}

.flex-footer {
  flex: 0 0 40px;
}

<!-- Semantic and straightforward -->

/* Grid 2D layout -->
.grid-page {
  display: grid;
  grid-template-rows: 60px 1fr 40px;
  min-height: 100vh;
}

.grid-header {
  grid-row: 1;
}

.grid-main {
  grid-row: 2;
}

.grid-footer {
  grid-row: 3;
}

<!-- More explicit grid structure -->
Hybrid approach: Flexbox + Grid

CSS
<!-- Use both together for complex layouts -->

<!-- Page structure: Grid -->
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr 40px;
  min-height: 100vh;
  gap: 20px;
}

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

<!-- Header structure: Flexbox -->
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo { flex: 0 0 auto; }
.nav { flex: 1; justify-content: center; }
.actions { flex: 0 0 auto; }

<!-- Content structure: Grid -->
.content {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.card {
  display: flex;  /* Flexbox for card internals -->
  flex-direction: column;
  gap: 10px;
}

.card-header { flex: 0 0 auto; }
.card-body { flex: 1; }
.card-footer { flex: 0 0 auto; }

<!-- Grid for page + card grid, Flexbox for components -->

/* Decision tree: -->
/* Is it one row OR one column? --> Flexbox -->
/* Is it rows AND columns together? --> Grid -->
/* Is it complex with nested layouts? --> Both! -->
Note
Flexbox is for one-dimensional layouts (navbar, sidebar, card internals). Grid is for two-dimensional layouts (page structure, dashboards, galleries). For complex layouts, use Grid for overall structure and Flexbox for component internals. They complement each other — you rarely need to choose just one.
Next
Master CSS Grid: [Grid Introduction](/css/grid-intro).