DEV Community

Alex Chen
Alex Chen

Posted on

CSS Flexbox & Grid: The Layout Guide I Wish I Had (2026)

CSS Flexbox & Grid: The Layout Guide I Wish I Had (2026)

CSS layout used to be a nightmare of floats and hacks. Flexbox and Grid changed everything. Here's how to actually use them.

Flexbox: One-Dimensional Layout

/* === The Mental Model ===
   Flexbox = ONE direction at a time (row OR column)
   Main axis = primary direction (flex-direction)
   Cross axis = perpendicular to main axis

   Think of it as: "I want these items in a LINE"
*/

/* Basic setup */
.container {
  display: flex;

  /* Main axis direction: */
  flex-direction: row;        /* Horizontal (default) */
  /* flex-direction: row-reverse; */ /* Right to left */
  /* flex-direction: column;      */ /* Vertical */
  /* flex-direction: column-reverse; */ /* Bottom to top */
}

/* Item alignment on MAIN axis (justify) */
.container {
  justify-content: flex-start;    /* Start of main axis (default) */
  /* justify-content: center;     */ /* Centered */
  /* justify-content: flex-end;    */ /* End of main axis */
  /* justify-content: space-between; */ /* Equal space BETWEEN items */
  /* justify-content: space-around;  */ /* Equal space AROUND items */
  /* justify-content: space-evenly; */ /* Equal space EVERYWHERE */
}

/* Item alignment on CROSS axis (align) */
.container {
  align-items: stretch;         /* Stretch to fill (default) */
  /* align-items: flex-start;   */ /* Start of cross axis */
  /* align-items: center;       */ /* Centered on cross axis */
  /* align-items: flex-end;     */ /* End of cross axis */
  /* align-items: baseline;     */ /* Text baseline alignment */
}

/* Individual item override */
.item:nth-child(2) {
  align-self: center;          /* This item centers itself! */
  flex-grow: 1;               /* This item takes all extra space */
  flex-shrink: 0;             /* This item never shrinks */
}

/* Wrapping when items overflow */
.container {
  flex-wrap: nowrap;           /* Single line (default, can overflow!) */
  /* flex-wrap: wrap;          */ /* Multi-line when needed */
  /* flex-wrap: wrap-reverse;  */ /* Wrap upwards */
}
/* Shorthand: flex-flow: row wrap; */

/* === Practical Flexbox Patterns === */

/* Navbar: Logo left, links right, centered vertically */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  height: 64px;
}

/* Card with icon + text, vertically centered */
.card-header {
  display: flex;
  align-items: center;
  gap: 12px;                   /* Gap between items (modern, no margin hacks!) */
}

/* Center anything (the holy grail of CSS!) */
.center-everything {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* Sticky footer (content pushes footer down) */
.page-layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.page-layout main {
  flex: 1;                    /* Takes remaining space */
}
.page-layout footer {
  flex-shrink: 0;             /* Never squishes */
}

/* Equal-width columns */
.equal-columns {
  display: flex;
  gap: 16px;
}
.equal-columns > * {
  flex: 1;                    /* Each child gets equal width */
  min-width: 0;              /* Prevents overflow with content */
}

/* Media object (image left, text right) */
.media-object {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.media-object img {
  flex-shrink: 0;            /* Image never squishes */
  width: 80px;
  height: 80px;
}
.media-object .content {
  flex: 1;                   /* Text takes remaining space */
}
Enter fullscreen mode Exit fullscreen mode

Grid: Two-Dimensional Layout

/* === The Mental Model ===
   Grid = TWO dimensions simultaneously (rows AND columns)

   Think of it as: "I want a TABLE-like layout"
   But way more powerful than tables ever were!
*/

/* Basic grid setup */
.grid-container {
  display: grid;

  /* Define columns: */
  grid-template-columns: 200px 1fr 200px;  /* Fixed / fluid / Fixed */
  /* grid-template-columns: repeat(3, 1fr); */ /* 3 equal columns */
  /* grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); */ /* Responsive! */
  /* grid-template-columns: 1fr 2fr 1fr; */ /* Ratio-based */

  /* Define rows: */
  grid-template-rows: auto 1fr auto;        /* Content-sized / fill / content-sized */
  /* grid-template-rows: repeat(4, 100px); */ /* 4 rows of 100px each */

  /* Gap between cells: */
  gap: 16px;                               /* Shorthand for row-gap + column-gap */
  /* row-gap: 8px; */
  /* column-gap: 16px; */
}

/* Placing items in the grid */
.header {
  grid-column: 1 / -1;                     /* Span ALL columns (from 1 to last) */
  /* grid-column: span 3;                  */ /* Span 3 columns */
  /* grid-column: 1 / 3;                   */ /* From column 1 to column 3 */
}

.sidebar {
  grid-row: 1 / 4;                         /* Span rows 1 through 4 */
  grid-column: 1;                           /* First column only */
}

.main-content {
  grid-column: 2 / -1;                      /* Everything except first column */
  grid-row: 2 / 4;
}

/* Named grid lines (much more readable!) */
.layout {
  display: grid;
  grid-template-columns: [sidebar] 240px [content-start] 1fr [content-end];
  grid-template-rows: [header] auto [main] 1fr [footer] auto;
}

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

/* Named areas (even more readable — visual layout in CSS!) */
.dashboard {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar main    main"
    "sidebar main    main"
    "footer  footer  footer";
  grid-template-columns: 240px 1fr 1fr;
  grid-template-rows: auto 1fr 1fr auto;
  gap: 16px;
}

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

/* Alignment within grid cell */
.grid-container {
  /* Align items inside their cells: */
  place-items: center;              /* Both axes (shorthand) */
  /* justify-items: center; */       /* Column axis */
  /* align-items: center;  */        /* Row axis */

  /* Align the entire grid tracks: */
  place-content: center;            /* When grid is larger than its items */
  /* justify-content: center; */
  /* align-content: center; */
}

/* Auto-fit / Auto-fill (responsive without media queries!) */
.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}
/* Creates as many 280px+ columns as will fit.
   If screen is 1200px wide → 4 columns.
   If screen is 600px wide  → 2 columns.
   Magic! */
Enter fullscreen mode Exit fullscreen mode

When to Use Which?

┌─────────────────────────────────────────────┐
│  Use FLEXBOX when:                          │
│  ✓ Laying out items in ONE direction        │
│  ✓ Navigation bars                          │
│  ✓ Card lists (horizontal or vertical)      │
│  ✓ Centering (anything!)                    │
│  ✓ Distributing space between items          │
│                                             │
│  Use GRID when:                             │
│  ✓ Full page layout (header/sidebar/main)    │
│  ✓ Complex 2D arrangements                  │
│  ✓ Overlapping elements                     │
│  ✓ Precise row AND column control           │
│  ✓ Responsive card grids                    │
│                                             │
│  They work TOGETHER:                        │
│  Use Grid for the PAGE layout               │
│  Use Flexbox for COMPONENTS inside the grid │
└─────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Common Patterns Solved

/* === Holy Grail Layout (Header + Sidebar + Main + Footer) === */
.holy-grail {
  display: grid;
  grid-template:
    "header header" auto
    "aside  main"  1fr
    "footer footer" auto
    / 260px 1fr;
  min-height: 100vh;
  gap: 0;
}
.holy-grail > header { grid-area: header; background: #e0e7ff; }
.holy-grail > aside  { grid-area: aside;  background: #fef3c7; }
.holy-grail > main   { grid-area: main;   padding: 24px; }
.holy-grail > footer { grid-area: footer; background: #e0e7ff; }

/* === Masonry-style Grid (CSS Grid + fit-content trick) === */
.masonry {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  grid-auto-rows: 10px;                /* Small base row size */
  gap: 16px;
}
.masonry > div {
  /* Each item spans multiple rows based on content: */
  grid-row: span 15;                  /* Adjust based on expected height */
  /* For truly dynamic masonry, use JavaScript or wait for masonry spec */
}

/* === Responsive Sidebar (Grid + media query) === */
.responsive-layout {
  display: grid;
  grid-template-columns: 260px 1fr;
  grid-template-areas: "aside main";
  gap: 24px;
}
@media (max-width: 768px) {
  .responsive-layout {
    grid-template-columns: 1fr;
    grid-template-areas: "aside" "main"; /* Stack vertically */
  }
}

/* === Aspect Ratio Cards (Grid makes this easy) === */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}
.card-grid > .card {
  aspect-ratio: 16 / 10;             /* All cards same proportion! */
  overflow: hidden;
  border-radius: 12px;
}

/* === Overlapping Elements (Hero section) === */
.hero {
  display: grid;
  grid-template-areas: "hero";
  /* All children share the SAME grid area → they overlap! */
}
.hero > .bg-image { grid-area: hero; z-index: 1; }
.hero > .content   { grid-area: hero; z-index: 2; align-self: center; justify-self: center; }
.hero > .overlay   { grid-area: hero; z-index: 1; background: rgba(0,0,0,0.4); }
Enter fullscreen mode Exit fullscreen mode

What's your go-to layout pattern? Flexbox purist or Grid enthusiast?

Follow @armorbreak for more practical developer guides.

Top comments (0)