Normal document flow
Before you add any layout CSS, the browser already arranges elements with normal flow. Two behaviors drive everything:
- Block elements (
div,p,h1,section) stack vertically and take the full width. - Inline elements (
span,a,strong) sit side by side within a line and are only as wide as their content.
All of layout is just overriding this default flow when you need rows, columns, or overlap. Most of the time, working with the flow is the simplest, most robust choice.
The display property
Every layout decision starts with display — it tells an element how to behave and how to treat its children.
| Value | Does |
|---|---|
| block | Stacks vertically, full width (the default for div). |
| inline | Flows in a line; width/height ignored. |
| inline-block | Flows in a line but accepts width/height & padding. |
| none | Removes the element entirely (no space kept). |
| flex | Makes children lay out in a row/column — Step 3. |
| grid | Makes children lay out in rows & columns — Step 4. |
flex and grid. You'll set them on a parent to arrange its children.Flexbox — layout in one direction
Add display: flex to a parent and its children line up in a row. Two properties control alignment: justify-content (along the row) and align-items (across it). Click to see it live:
.row { display: flex; gap: 10px; justify-content: space-between; }
flex-wrap: wrap so items drop to a new line on small screens.CSS Grid — layout in two directions
Grid arranges children into rows and columns at once. Define the columns with grid-template-columns; 1fr means “one share of the free space.” Click a column count:
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
repeat(auto-fit, minmax(200px, 1fr)) fills as many columns as fit and wraps automatically — a fluid card gallery with no media queries. (That's the “auto-fit” button above.)Positioning & layering
Flexbox and Grid arrange things in flow. position lets you take an element out of flow or pin it relative to something.
| position | Behaves like |
|---|---|
| static | Default — normal flow, ignores top/left. |
| relative | Normal flow, but nudge-able & an anchor for absolute children. |
| absolute | Out of flow, placed relative to nearest positioned ancestor. |
| fixed | Pinned to the viewport — stays on scroll (sticky headers/FAB). |
| sticky | Scrolls normally, then “sticks” at a top offset. |
Live: position: sticky — scroll inside this box
Scroll this panel. The purple bar stays pinned at the top once it reaches it — the same trick behind sticky section headers and the table-of-contents bar on this very page.
Lorem ipsum content to create scroll height. Sticky positioning needs a top value and a scroll container taller than the element.
Keep scrolling…
…the header never leaves until its parent does.
That's positioning in action.
position: absolute to build a layout usually means Flexbox or Grid is the better tool.Building a full page layout
The classic app shell — header, sidebar, main, footer — is a few lines of Grid. This is the “holy grail” layout:
.app { display: grid; grid-template-columns: 220px 1fr; fixed sidebar, fluid main grid-template-rows: auto 1fr auto; header, body, footer } header, footer { grid-column: 1 / -1; } span both columns
.container { max-width: 1100px; margin: 0 auto; padding: 0 24px; } keeps text from stretching too wide on big screens.Responsive layouts
Layouts must adapt from phone to desktop. Design mobile-first: simple single-column base styles, then add columns at larger widths with a @media query.
.layout { display: grid; grid-template-columns: 1fr; gap: 20px; } phone @media (min-width: 768px) { .layout { grid-template-columns: 240px 1fr; } tablet+: sidebar appears }
<meta name="viewport" content="width=device-width, initial-scale=1.0">.Centering, finally solved
“How do I center a div?” is the oldest CSS question. Modern layout makes it trivial — both axes at once:
.center { display: grid; place-items: center; horizontal + vertical, done } /* or with flex */ .center { display: flex; justify-content: center; align-items: center; }
margin: 0 auto (with a max-width set).Flexbox or Grid? A quick rule
| If you're… | Use |
|---|---|
| One line | Flexbox — navbar, button row, tags, centering one item. |
| Two dimensions | Grid — page shell, card gallery, dashboard, image mosaic. |
| Content-driven sizing | Flexbox — items size to their content, wrap as needed. |
| Layout-driven sizing | Grid — you define the tracks, content fills them. |
Layout checklist
- Work with normal flow; only override when you need rows/columns/overlap
- Flexbox for one-dimensional rows; Grid for two-dimensional layouts
- Spacing done with
gap, not margins on every child -
position: absolute/fixedreserved for overlays & sticky bars - Mobile-first base, columns added with
@media (min-width: …) - Content column capped with
max-width+margin: 0 auto - The viewport meta tag is in the HTML
<head>