Back to blog
Frontend Engineeringbeginner

CSS Flexbox and Grid — Complete Layout Guide

Master CSS Flexbox and CSS Grid with practical examples. Build responsive navbars, card grids, holy grail layouts, and understand when to use each.

Asma HafeezApril 17, 20267 min read
cssflexboxgridlayoutresponsive
Share:š•

CSS Flexbox and Grid

Before Flexbox and Grid, CSS layouts were hacked together with floats and positioning. Now these two tools handle 95% of everything you need. Learn both — they complement each other.

Rule of thumb: Flexbox for one-dimensional layouts (row OR column). Grid for two-dimensional layouts (rows AND columns simultaneously).


CSS Flexbox

Apply display: flex to a container to turn its direct children into flex items.

The Main Axis and Cross Axis

The key mental model:

  • Main axis = the direction flex items flow (flex-direction)
  • Cross axis = perpendicular to main axis
CSS
.container {
  display: flex;
  flex-direction: row;         /* default: left to right */
  /* flex-direction: column;   top to bottom */
  /* flex-direction: row-reverse; right to left */
  /* flex-direction: column-reverse; bottom to top */
}

Alignment Properties

CSS
.container {
  display: flex;

  /* Align along MAIN axis */
  justify-content: flex-start;    /* default — pack at start */
  justify-content: flex-end;      /* pack at end */
  justify-content: center;        /* center */
  justify-content: space-between; /* first/last at edges, rest evenly spaced */
  justify-content: space-around;  /* equal space around each item */
  justify-content: space-evenly;  /* equal space between all items and edges */

  /* Align along CROSS axis (single line) */
  align-items: stretch;     /* default — fill cross axis */
  align-items: flex-start;  /* align to start of cross axis */
  align-items: flex-end;    /* align to end */
  align-items: center;      /* center vertically (if row direction) */
  align-items: baseline;    /* align text baselines */

  /* Align multiple lines (only when flex-wrap: wrap) */
  align-content: flex-start;
  align-content: center;
  align-content: space-between;
}

Wrapping

CSS
.container {
  flex-wrap: nowrap;    /* default — overflow if items don't fit */
  flex-wrap: wrap;      /* wrap to next line */
  flex-wrap: wrap-reverse;
}

Gap

CSS
.container {
  display: flex;
  gap: 16px;           /* space between all items */
  gap: 16px 8px;       /* row-gap column-gap */
  row-gap: 16px;
  column-gap: 8px;
}

Flex Item Properties

CSS
.item {
  /* How much the item grows relative to siblings (default: 0 = don't grow) */
  flex-grow: 1;   /* take up remaining space */
  flex-grow: 2;   /* take twice as much remaining space as flex-grow:1 items */

  /* How much the item shrinks (default: 1 = can shrink) */
  flex-shrink: 0; /* don't shrink — keep its width */

  /* Starting size before grow/shrink */
  flex-basis: 200px;  /* start at 200px, then grow/shrink */
  flex-basis: auto;   /* use width/content size */
  flex-basis: 0;      /* start from nothing, then grow */

  /* Shorthand: grow shrink basis */
  flex: 1 1 auto; /* default */
  flex: 1;        /* grow:1, shrink:1, basis:0 — most common */
  flex: 0 0 200px; /* fixed 200px — don't grow, don't shrink */

  /* Override align-items for this specific item */
  align-self: center;

  /* Change order (default: 0) */
  order: -1;  /* move to beginning */
  order: 1;   /* move to end */
}

Flexbox Patterns

Centered Content (most common CSS question)

CSS
.centered {
  display: flex;
  justify-content: center;
  align-items: center;
  /* For full-screen centering: */
  min-height: 100vh;
}

Navigation Bar

CSS
.nav {
  display: flex;
  align-items: center;
  padding: 0 24px;
  height: 64px;
}

.nav-logo { margin-right: auto; } /* pushes everything else to the right */

.nav-links {
  display: flex;
  gap: 8px;
}

Equal-Width Cards

CSS
.card-row {
  display: flex;
  gap: 16px;
}

.card {
  flex: 1;  /* all cards share space equally */
}

Sticky Footer

CSS
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main { flex: 1; } /* takes all available space, pushes footer down */
footer { /* natural height */ }

CSS Grid

Grid divides a container into rows and columns, and you place items into cells.

Defining the Grid

CSS
.grid {
  display: grid;

  /* Define columns */
  grid-template-columns: 200px 200px 200px;       /* 3 fixed columns */
  grid-template-columns: 1fr 1fr 1fr;              /* 3 equal columns */
  grid-template-columns: 200px 1fr;                /* fixed + flexible */
  grid-template-columns: repeat(3, 1fr);           /* shorthand */
  grid-template-columns: repeat(3, minmax(200px, 1fr)); /* min 200px, share rest */

  /* Define rows */
  grid-template-rows: 80px 1fr 60px;  /* fixed header, flexible main, fixed footer */
  grid-auto-rows: 200px;              /* all implicit rows are 200px */
  grid-auto-rows: minmax(150px, auto); /* min 150px, grow with content */

  /* Gap */
  gap: 16px;
  column-gap: 16px;
  row-gap: 8px;
}

Responsive Grid with auto-fill

CSS
/* Auto-fill: as many columns as fit, minimum 250px each */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

/* auto-fit vs auto-fill:
   auto-fill: keeps empty columns (items don't stretch to fill row)
   auto-fit: collapses empty columns (items stretch to fill row) */

Placing Items

CSS
/* By line number (1-based, negative counts from end) */
.item {
  grid-column: 1 / 3;      /* from column line 1 to 3 (spans 2 columns) */
  grid-column: 1 / -1;     /* full width (from line 1 to last line) */
  grid-column: span 2;     /* span 2 columns from current position */
  grid-row: 1 / 2;
  grid-row: span 2;        /* span 2 rows */
}

Named Template Areas

CSS
.layout {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 64px 1fr 60px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
}

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

Grid Patterns

Holy Grail Layout

CSS
body {
  display: grid;
  grid-template-columns: 240px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  min-height: 100vh;
  gap: 0;
}
header  { grid-area: header;  }
.sidebar{ grid-area: sidebar; }
main    { grid-area: content; }
aside   { grid-area: aside;   }
footer  { grid-area: footer;  }

Magazine / Asymmetric Grid

CSS
.magazine {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.featured {
  grid-column: span 2;
  grid-row: span 2;
}

Image Gallery with Masonry-like Effect

CSS
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px;
  gap: 8px;
}

.gallery-item:nth-child(3n+1) { grid-row: span 2; } /* every 3rd-1 is taller */

Flexbox vs Grid — When to Use Each

| Scenario | Use | |----------|-----| | Navigation bar (horizontal) | Flexbox | | Card row (equal widths) | Either | | Full-page layout (header/sidebar/main/footer) | Grid | | Responsive card grid | Grid (auto-fill) | | Center one element | Flexbox | | Item grows to fill remaining space | Flexbox | | Two-dimensional overlap/spanning | Grid | | Unknown number of items | Flexbox |

They work together — use Grid for page layout, Flexbox inside components.


Complete Example: App Layout

HTML
<!-- HTML -->
<body class="layout">
  <header class="header">
    <a href="/" class="logo">App</a>
    <nav class="nav">
      <a href="/dashboard">Dashboard</a>
      <a href="/courses">Courses</a>
      <a href="/settings">Settings</a>
    </nav>
    <button class="btn">Sign In</button>
  </header>
  <aside class="sidebar">...</aside>
  <main class="main">
    <div class="cards">
      <div class="card">...</div>
      <div class="card">...</div>
      <div class="card">...</div>
    </div>
  </main>
  <footer class="footer">Ā© 2026</footer>
</body>
CSS
/* Page layout — Grid */
.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 48px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; padding: 24px; }
.footer  { grid-area: footer; }

/* Header — Flexbox */
.header {
  display: flex;
  align-items: center;
  padding: 0 24px;
  gap: 16px;
  border-bottom: 1px solid #e5e7eb;
}
.nav { display: flex; gap: 4px; }
.btn { margin-left: auto; }

/* Cards — responsive Grid */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

/* Card — Flexbox for internal layout */
.card {
  display: flex;
  flex-direction: column;
  border-radius: 12px;
  overflow: hidden;
}
.card-content { flex: 1; padding: 16px; } /* grows to push footer down */
.card-footer   { padding: 12px 16px; }    /* stays at bottom */

Key Takeaways

  1. Flexbox = one-dimensional, justify-content on main axis, align-items on cross axis
  2. Grid = two-dimensional, grid-template-columns/rows define structure, grid-area places items
  3. gap works in both — prefer it over margins between items
  4. repeat(auto-fill, minmax(250px, 1fr)) is the magic responsive grid pattern
  5. flex: 1 makes an item fill remaining space — use it for the main content area
  6. Named template areas (grid-template-areas) make complex layouts readable

Enjoyed this article?

Explore the Frontend Engineering learning path for more.

Found this helpful?

Share:š•

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.