Flow, flexbox and grid
One thing is still missing. However wide the screen, your cards sit in a single column. This lesson is layout — the CSS that arranges boxes in two dimensions — and it's the last piece that turns a page into a gallery.
Normal flow: what boxes do on their own
Before you arrange anything, know the default. Every element is either block or inline:
- Block elements —
div,p,h1,section,article— take the full width available and stack one on top of the next. That's why your cards form a column: each<article>is a block, so each drops below the last. - Inline elements —
a,span, and by defaultimgandbutton— sit in a line, flowing left to right like words in a sentence, only as wide as their content.
That stacking is normal flow. Layout is what you reach for when normal flow isn't the shape you want.
Flexbox: a row (or a column) of items
You've been using flexbox since you built the navbar — this is what it was doing. display: flex on a container lays its direct children along one axis:
.navbar { display: flex; align-items: center; gap: 1.5rem; }
That's the nav bar: brand, links and everything else in a row, vertically centred, with a gap between them. The card uses the same tool the other way:
.picture-card { display: flex; flex-direction: column; }
— header on top, body below, in a column. A few flex properties do most of the work: gap spaces the children, align-items positions them across the axis, justify-content distributes them along it, and flex: 1 on a child tells it to grow and eat the leftover space — which is why .nav-links pushes everything after it to the right. The one thing to hold onto: flexbox is one-dimensional — a single row, or a single column.
Grid: rows and columns at once
A gallery isn't a row — it's a grid of cells that wraps across as many columns as the screen allows. That's two dimensions, and it's what display: grid is for. One rule does it:
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
Read the middle line inside out:
minmax(280px, 1fr)— each column is at least 280px and at most one fraction (1fr) of the leftover space. So columns never shrink below 280, and when there's spare room they share it equally.repeat(auto-fill, …)— make as many of those columns as fit the container. On a wide screen that's four or five; as the screen narrows, the grid drops to three, then two, then one.
That is the whole trick: the grid counts its own columns from the available width. No media query, no breakpoints — auto-fill and fr make it respond on their own. (gap: 1.5rem sets the space between cells, replacing the old habit of margins that collapse and fight each other.)
A related keyword you'll meet is auto-fit: nearly identical, but it collapses empty columns so a few items stretch to fill the row, where auto-fill keeps the empty column slots. For a gallery that should keep its card size, auto-fill is the right pick.
Choosing between them
They're not rivals; they answer different questions.
- Reach for flexbox when you have a line of items whose sizes drive the layout — a nav bar, a toolbar, the stacked inside of a card. One dimension.
- Reach for grid when you're placing items into a two-dimensional arrangement — a gallery, a page skeleton, a form of aligned rows and columns.
Rule of thumb: a line of content → flex; a grid of cells → grid. Your page already uses flex for the small structures; next you add the one grid that lays out the gallery.