The Mental Model
The simplest way to think about it: Flexbox is one-dimensional (a row OR a column), while Grid is two-dimensional (rows AND columns simultaneously). This isn't about capability โ both can create complex layouts โ but about which approach is more natural for the task.
A useful rule of thumb: use Flexbox for components, use Grid for layouts. A navigation bar, a button group, a card's internal layout โ these are Flexbox territory. A page layout, a dashboard, a card grid โ these are Grid territory.
When to Use Flexbox
Flexbox excels when you need to distribute items along a single axis with flexible sizing. Common Flexbox patterns include:
/* Navigation bar */
.nav {
display: flex;
align-items: center;
gap: 8px;
}
/* Push last item to the right */
.nav .spacer { flex: 1; }
/* Center content vertically & horizontally */
.center-me {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
/* Card footer with actions */
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
Flexbox lets content dictate the layout. Items grow and shrink based on their content and the available space. Grid lets the container dictate the layout โ you define the structure first, then place content into it.
When to Use Grid
CSS Grid is the right choice when you need to control both rows and columns, or when the layout structure is known in advance:
/* Page layout */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
/* Card grid */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
/* Dashboard layout */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.widget-large { grid-column: span 2; grid-row: span 2; }
Combining Grid & Flexbox
The real power comes from using both together. A typical pattern: Grid for the overall page and card arrangement, Flexbox for the internal layout of each card:
/* Grid for the card arrangement */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
/* Flexbox for internal card layout */
.card {
display: flex;
flex-direction: column;
}
.card-body { flex: 1; }
.card-footer {
display: flex;
justify-content: space-between;
margin-top: auto;
}
Common Layout Patterns
Holy Grail Layout
The classic header-sidebar-content-footer layout, elegantly solved by Grid:
.layout {
display: grid;
grid-template: auto 1fr auto / 240px 1fr;
min-height: 100vh;
}
header, footer { grid-column: 1 / -1; }
aside { grid-row: 2; }
main { grid-row: 2; grid-column: 2; }
Sticky Footer
Keeping the footer at the bottom even when content is short:
/* Grid approach */
body { display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; }
/* Flexbox approach */
body { display: flex; flex-direction: column; min-height: 100vh; }
main { flex: 1; }
Responsive Without Media Queries
One of Grid's superpowers is creating responsive layouts without any media queries. The auto-fill / auto-fit keywords with minmax() let the browser decide how many columns to use:
/* Cards: min 280px wide, fill available space */
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
/* That's it. No media queries needed. */
The difference between auto-fill and auto-fit: auto-fill creates as many tracks as will fit, even empty ones. auto-fit collapses empty tracks so remaining items stretch to fill the row. For most card grids, auto-fill is what you want.
Build Beautiful UIs Faster
Combine great layouts with our free CSS generators for gradients, shadows, and glass effects.
Explore All Tools โ