Introduction to HTML & CSS · Lesson 3 of 5

Flexbox & CSS Grid for Modern Layouts

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