CSS Modern Layout: Grid, Flexbox, and Container Queries
CSS Modern Layout: Grid, Flexbox, and Container Queries
CSS Modern Layout Techniques: Grid, Flexbox, and Container Queries in 2026
CSS layout has undergone a revolution. Gone are the days of float-based hacks and clearfix workarounds. In 2026, three layout systems form the foundation of modern CSS: CSS Grid for two-dimensional layouts, Flexbox for one-dimensional alignment, and Container Queries for truly component-responsive design. Together, they give developers unprecedented control over page structure.
According to the 2025 State of CSS survey, Grid is now used by 91% of developers, Flexbox by 98%, and Container Queries by 47% with rapidly growing adoption. This guide covers each technology in depth with practical examples you can use immediately.
CSS Flexbox: One-Dimensional Layout Mastery
When to Use Flexbox
Flexbox excels at distributing space along a single axis — either horizontal or vertical. Use it for:
- Navigation bars and toolbars
- Centering content vertically and horizontally
- Card rows that need equal height
- Form input groups
- Any layout where items flow in one direction
Essential Flexbox Patterns
Pattern 1: The Holy Grail Navigation
A navigation bar with logo on the left, links in the center, and actions on the right:
/* Navigation with three sections */
.navbar {
display: flex;
align-items: center;
padding: 1rem 2rem;
gap: 1rem;
}
.navbar-logo {
flex: 0 0 auto; /* Don't grow, don't shrink */
}
.navbar-links {
display: flex;
flex: 1 1 auto; /* Grow to fill space */
justify-content: center;
gap: 2rem;
}
.navbar-actions {
flex: 0 0 auto;
display: flex;
gap: 0.5rem;
}Pattern 2: Equal-Height Cards
Cards that always match the height of the tallest sibling, with the button pushed to the bottom:
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
display: flex;
flex-direction: column;
flex: 1 1 300px; /* Grow, shrink, minimum 300px */
max-width: 400px;
padding: 1.5rem;
border: 1px solid #e2e8f0;
border-radius: 8px;
}
.card-body {
flex: 1; /* Pushes footer to bottom */
}
.card-footer {
margin-top: auto; /* Sticks to bottom regardless of content height */
}Pattern 3: Perfect Centering
The simplest way to center anything both vertically and horizontally:
.centered-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Alternative: even simpler with place-content */
.centered-container {
display: flex;
place-content: center;
min-height: 100vh;
}Flexbox Gap: The Modern Spacing Solution
The gap property (supported in Flexbox since 2021 with now 99% browser support) replaces the old margin-based spacing hacks:
/* Old approach: margin with negative margin wrapper */
.old-list > * {
margin: 0 8px 8px 0;
}
.old-list {
margin-right: -8px; /* Compensate */
}
/* Modern approach: gap */
.modern-list {
display: flex;
flex-wrap: wrap;
gap: 8px; /* Clean, no hacks needed */
}CSS Grid: Two-Dimensional Layout Power
When to Use Grid
CSS Grid is designed for two-dimensional layouts where you control both rows and columns simultaneously. Use it for:
- Page-level layouts (header, sidebar, main, footer)
- Image galleries and masonry layouts
- Dashboard layouts with varying-size widgets
- Any layout requiring precise row and column alignment
Essential Grid Patterns
Pattern 1: Responsive Grid Without Media Queries
The most powerful Grid technique is auto-fit with minmax(), which creates a responsive grid that adjusts column count automatically:
.auto-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Result:
- 4 columns on large screens
- 3 columns on medium screens
- 2 columns on tablets
- 1 column on mobile
ALL without a single media query */Pattern 2: The Classic Page Layout
A full page layout with named grid areas makes the template readable and maintainable:
.page-layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
/* Responsive: stack on mobile */
@media (max-width: 768px) {
.page-layout {
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-columns: 1fr;
}
}Pattern 3: Dashboard with Spanning Widgets
Grid's spanning capabilities make it perfect for dashboards where widgets vary in size:
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(200px, auto);
gap: 1rem;
}
.widget-large {
grid-column: span 2;
grid-row: span 2;
}
.widget-wide {
grid-column: span 2;
}
.widget-tall {
grid-row: span 2;
}
/* All other widgets auto-place into remaining cells */Subgrid: Aligning Nested Content
Subgrid, now supported in all major browsers (Chrome 117+, Firefox 71+, Safari 16+), lets nested grids inherit track sizing from their parent. This solves the common problem of aligning card titles, bodies, and footers across a row:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
grid-template-rows: subgrid; /* Inherit row tracks from parent */
grid-row: span 3; /* Card occupies 3 rows: title, body, footer */
}
/* Now all card titles align, all bodies align, all footers align
regardless of content length in each card */Container Queries: Component-Level Responsiveness
The Problem with Media Queries
Media queries respond to the viewport width. But components live inside containers that may be any size — a sidebar, a modal, a grid column. A card component that looks great in a 3-column layout breaks when placed in a narrow sidebar, even though the viewport hasn't changed.
Container Queries solve this by letting components respond to their container's size instead of the viewport.
Setting Up Container Queries
First, establish a containment context on the parent element:
/* Define the container */
.card-wrapper {
container-type: inline-size;
container-name: card; /* Optional: name it for clarity */
}
/* Shorthand */
.card-wrapper {
container: card / inline-size;
}
/* Now the card responds to its container's width, not the viewport */
.card {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@container card (min-width: 400px) {
.card {
grid-template-columns: 150px 1fr;
}
}
@container card (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr;
gap: 1.5rem;
}
.card-title {
font-size: 1.5rem;
}
}Practical Container Query Example: Product Card
A product card that adapts whether it is in a wide main content area or a narrow sidebar:
/* Containment context */
.product-container {
container: product / inline-size;
}
/* Default: narrow layout (sidebar, mobile) */
.product-card {
display: flex;
flex-direction: column;
padding: 1rem;
border-radius: 8px;
border: 1px solid #e2e8f0;
}
.product-card img {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
border-radius: 4px;
}
.product-info {
padding-top: 0.75rem;
}
.product-price {
font-size: 1.25rem;
font-weight: 700;
}
/* Medium: horizontal card */
@container product (min-width: 450px) {
.product-card {
flex-direction: row;
gap: 1.5rem;
}
.product-card img {
width: 180px;
flex-shrink: 0;
}
}
/* Large: full-featured display */
@container product (min-width: 700px) {
.product-card {
padding: 1.5rem;
}
.product-card img {
width: 250px;
}
.product-price {
font-size: 1.75rem;
}
.product-actions {
display: flex;
gap: 0.5rem;
}
}Container Query Units
Container Queries also introduce new units that are relative to the container's size:
- cqw — 1% of the container's width
- cqh — 1% of the container's height
- cqi — 1% of the container's inline size
- cqb — 1% of the container's block size
- cqmin / cqmax — the smaller / larger of cqi and cqb
.responsive-heading {
/* Font size scales with container width */
font-size: clamp(1rem, 4cqi, 2.5rem);
}
.responsive-padding {
/* Padding scales with container */
padding: clamp(0.5rem, 3cqi, 2rem);
}Combining All Three: A Real-World Layout
The true power emerges when you combine Grid, Flexbox, and Container Queries together. Here is a complete dashboard layout:
/* Grid for the overall page layout */
.dashboard {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 64px 1fr;
grid-template-areas:
"nav header"
"nav main";
min-height: 100vh;
}
/* Flexbox for the header toolbar */
.dashboard-header {
grid-area: header;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 2rem;
}
/* Grid for the widget area */
.dashboard-main {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
padding: 1.5rem;
}
/* Container queries for individual widgets */
.widget-wrapper {
container: widget / inline-size;
}
.widget {
padding: 1rem;
border-radius: 8px;
background: white;
}
@container widget (min-width: 500px) {
.widget-chart {
aspect-ratio: 16 / 9;
}
.widget-header {
display: flex;
justify-content: space-between;
align-items: center;
}
}
/* Flexbox for the sidebar navigation */
.dashboard-nav {
grid-area: nav;
display: flex;
flex-direction: column;
gap: 0.25rem;
padding: 1rem;
background: #1a1a2e;
}Decision Guide: Grid vs Flexbox vs Container Queries
Use this decision framework to choose the right tool:
- Layout in one direction? → Flexbox
- Layout in two directions (rows and columns)? → Grid
- Component should adapt to its container, not the viewport? → Container Queries
- Auto-flowing content of unknown quantity? → Flexbox (wrap) or Grid (auto-fit)
- Precise placement of items in named areas? → Grid (template-areas)
- Aligning nested content across siblings? → Grid (subgrid)
In practice, most layouts use a combination. Grid structures the page, Flexbox aligns items within sections, and Container Queries make components portable and reusable across different contexts. Master all three, and you can build any layout without a single line of JavaScript.
Browser Support in 2026
All three technologies have excellent browser support:
- Flexbox: 99.5% global support — fully safe for production
- CSS Grid: 98% global support — fully safe for production
- Subgrid: 93% global support (Chrome 117+, Firefox 71+, Safari 16+)
- Container Queries: 92% global support (Chrome 105+, Firefox 110+, Safari 16+)
- Container Query Units: 91% global support
For the small percentage of older browsers that don't support Container Queries, the default (non-queried) styles serve as a natural fallback, so your layouts degrade gracefully.