Matheion

MA-WEB1 · Module 14

Flexbox and CSS Grid

Topics: Flex containers · justify and align · Grid columns · auto-fill galleries

Overview

Session 14 — Flexbox and CSS Grid

You will learn the two modern CSS layout engines: flexbox for one-directional layouts (nav bars, button rows, equal cards) with justify-content/align-items/gap/flex, and CSS Grid for two-dimensional layouts (page columns, wrapping galleries) with grid-template-columns, fr units, repeat, and grid-column. You will lay out the café's nav, main/aside page, and gallery.

Plan: ideas → worked layouts → bridge → short drills → reveal.

Time: about 60–70 minutes if you say flex-or-grid-and-why for every layout before writing it.

Concepts

Session 14 — Flexbox and CSS Grid

The one-paragraph story

Flexbox and Grid are the two modern CSS layout engines. Flexbox arranges a row (or column) of items in one direction and is ideal for navigation bars, toolbars, and cards-in-a-row; Grid arranges content on a two-dimensional grid of rows and columns and is ideal for whole-page layouts and galleries. The model in both is the same shape: a container (with display: flex or display: grid) governs its items (its direct children). This session lays out the café site — a horizontal nav, a main-plus-aside two-column region, and a gallery grid — with ten properties total.


Flexbox: one direction at a time

nav ul {
  display: flex;
  gap: 16px;
}

A flex container lays its items along one main axis. The default flex-direction: row lays them left to right — the Session 13 nav bar, now without any inline-block trick. flex-direction: column stacks them top to bottom.

Two spacing properties do most of the work:

.flex-row {
  display: flex;
  gap: 12px;                /* space between items   */
  justify-content: center;  /* placement on the main axis  */
  align-items: center;      /* placement on the cross axis  */
}
  • gap — the space between items (no margin hacks).
  • justify-content — distributes items along the main axis: flex-start (start), flex-end (end), center, space-between (first and last at the edges, equal gaps between), space-around.
  • align-items — aligns items along the cross axis: stretch (default — items fill the cross size), flex-start, flex-end, center.

For a row, justify-content is horizontal placement and align-items is vertical; for a column they swap. The mental model: justify = along, align = across.

Flexible sizing is flexbox's superpower. Items can grow or shrink to fill the container:

nav li { flex: 1; }

flex: 1 means "grow to share the leftover space equally". Three flex: 1 items split the width evenly — a full-width nav or a row of equal cards without calculating percentages.


Centring, the flexbox way

The most common layout request in all of CSS:

.hero {
  display: flex;
  justify-content: center;
  align-items: center;
}

Any box becomes a centring machine: its child sits dead centre in both axes. This is the text-align centring of box layouts.


Grid: two dimensions

Grid divides a container into rows and columns and places items into them:

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

grid-template-columns: repeat(3, 1fr) — three equal columns; 1fr is "one fraction of the free space", so three of them split the width equally. The gallery's direct children (the cards) fall into the cells automatically, in order. A fourth card wraps to the second row.

The same sizing grammar covers rows:

.page-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;   /* main column twice the aside */
  gap: 24px;
}

Two columns in a 2:1 ratio — the café's main-plus-aside layout. fr units are the grid equivalent of flex: 1: they divide available space in proportion to their number.


Explicit placement

Automatic placement fills cells in order. For precise control, name a cell or stretch an item:

.banner {
  grid-column: 1 / -1;   /* span from the first to the last column */
}

grid-column: 1 / -1 makes the banner stretch across the whole grid. The -1 means "the last line" — a neat way to say "full width" in any grid.


Choosing between flex and grid

The decision rule:

  • One direction — a nav bar, a button row, a set of cards in a line → flexbox.
  • Two dimensions — a page with header/main/aside/footer, a photo gallery that wraps into rows → grid.
  • Both work, size matters — a row of equal cards can be flex (flex: 1) or grid (repeat(n, 1fr)); grid wraps into rows automatically when the container narrows, flex (alone) does not. When you need wrapping, prefer grid.

A handy mental shortcut: flex is the sequence engine; grid is the map engine.


The café site, laid out

/* Nav: one row */
nav ul {
  display: flex;
  gap: 24px;
  list-style: none;
  padding: 0;
}

/* Main + aside: two columns */
.page {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 24px;
}

/* Gallery: wrapping cards */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

Three layouts, ten properties. The nav is a flex row; the page is a two-column grid (2:1); the gallery is a grid that wraps cards into columns at least 200 px wide (auto-fill + minmax — the responsive idiom, examined in Session 15).


Pitfalls to watch for

  • justify and align are not interchangeable — justify runs along the main axis, align along the cross axis; in a column they swap meanings.
  • display: flex/grid only affects direct children — a flex container does not lay out grandchildren.
  • Forgetting gap vs margins — use gap on the container instead of per-item margins.
  • Grid without grid-template-columns — a grid with one column is just a flex column; the columns definition is what makes it a grid.

Examples

Session 14 — Worked examples

Example A — The nav bar as flex

nav ul {
  display: flex;
  gap: 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}

The Session 4 nav markup — <ul> with three <li><a> — becomes a horizontal row with 24 px gaps. Each li is a flex item; the a links sit inside. No floats, no inline-block: flex does the row.


Example B — A centered hero

.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 300px;
}

The hero's content (an h1, a paragraph) sits dead centre both horizontally and vertically. justify-content: center centres along the row axis; align-items: center centres along the column axis.


Example C — Equal cards with flex: 1

.cards {
  display: flex;
  gap: 16px;
}
.cards .card {
  flex: 1;
}

Three .cards share the container's width equally — each flex: 1 claims the same share of leftover space. Add a fourth card and all four shrink to fit: the sizing is automatic.


Example D — The main-plus-aside grid

.page {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 24px;
}
<div class="page">
  <main>
    <h1>Welcome to the Harbor Café</h1>
    <p>…</p>
  </main>
  <aside>
    <h2>Opening hours</h2>
    <p>Daily, 7:00–15:00.</p>
  </aside>
</div>

Two columns: main gets two fractions, aside gets one — a 2:1 split with 24 px between them. The Session 8 skeleton's vertical stack is now a two-column page. On a narrow screen this grid stays two columns (Session 15 fixes that with media queries).


Example E — A wrapping gallery

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

Cards flow into columns at least 200 px wide; when the container is wide enough for another 200 px column, one appears — the grid auto-fills and wraps rows. A 640 px container gets three columns; a 430 px container gets two. This single line is the responsive gallery.


Example F — A full-width banner inside a grid

.newsletter {
  grid-column: 1 / -1;
}

Inside the .page grid (two columns), a .newsletter item with grid-column: 1 / -1 spans from the first column line to the last — full width under both columns. -1 means "the last line", which makes "full width" independent of the column count.

Practice check — flexbox and grid

Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.

  1. 1.A horizontal navigation bar is best built with:

  2. 2.In a row flex container, `justify-content` controls placement along the:

  3. 3.`grid-template-columns: repeat(3, 1fr)` creates:

  4. 4.`gap: 16px` on a flex container sets:

  5. 5.A photo gallery that should wrap into rows as the screen narrows is best built with: