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
justifyandalignare not interchangeable — justify runs along the main axis, align along the cross axis; in a column they swap meanings.display: flex/gridonly affects direct children — a flex container does not lay out grandchildren.- Forgetting
gapvs margins — usegapon 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.A horizontal navigation bar is best built with:
2.In a row flex container, `justify-content` controls placement along the:
3.`grid-template-columns: repeat(3, 1fr)` creates:
4.`gap: 16px` on a flex container sets:
5.A photo gallery that should wrap into rows as the screen narrows is best built with: