CSS Layout: Flexbox and Grid Without the Guesswork
Most layout frustration comes from using the wrong tool. Flexbox arranges items along one axis. Grid arranges them in two. Once that choice is automatic, the rest of CSS layout gets considerably calmer.
One axis: flexbox
Flexbox distributes space along a single direction — a row of navigation links, a toolbar, a card with a button pinned to the bottom.
.nav {
display: flex;
align-items: center; /* vertical alignment in a row */
justify-content: space-between; /* horizontal distribution */
gap: 12px; /* space between items, no margins needed */
}
Two properties do the heavy lifting. justify-content works along the main axis, align-items across it. Flip flex-direction to column and the two swap meaning, which is the single most common source of confusion. gap replaced the old margin tricks and works in every current browser.
For items that should grow or shrink, flex: 1 is shorthand for "take an equal share of the leftover space". flex: 0 0 240px means "stay 240 pixels, do not grow or shrink".
Two axes: grid
Grid places items into rows and columns you define in advance. It is the right tool for page layouts and card collections.
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 18px;
}
That one declaration produces a responsive card grid with no media queries at all. It reads as: make as many equal columns as fit, each at least 260 pixels wide, and let them share any extra space. At 1,400 pixels it might make five columns; on a phone it collapses to one.
For a page shell, named areas keep the intent readable:
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-areas:
"sidebar content";
}
@media (max-width: 800px) {
.page {
grid-template-columns: 1fr;
grid-template-areas: "content" "sidebar";
}
}Sizing that survives real content
Fixed pixel widths break the moment content is longer than expected. These keep working:
min(),max()andclamp()—font-size: clamp(24px, 4vw, 44px)scales a heading between two limits with no breakpoints.minmax()in grid, for columns with a floor and a ceiling.max-width: 70chon body text. Measured in characters, it keeps lines at a comfortable reading length regardless of font size.aspect-ratio: 16 / 9on video and image containers, which reserves the right space before media loads and stops the page jumping.
Mobile first, and why the order matters
Write the narrow-screen layout as the default, then add complexity with min-width media queries. The result is less CSS, because the simple case needs almost no rules, and phones download the styles they actually use first.
.layout { display: grid; gap: 16px; } /* phone: one column */
@media (min-width: 760px) {
.layout { grid-template-columns: 2fr 1fr; } /* tablet and up */
}
Give the page a 16-pixel side gutter and check at 320 pixels wide. If anything scrolls sideways, something inside has a fixed width — usually a table, a long unbroken string, or an embedded iframe.
Custom properties for theming
CSS variables make a colour scheme changeable in one place, and make dark mode a few lines instead of a parallel stylesheet.
:root {
--bg: #ffffff;
--text: #0f172a;
}
:root[data-theme="dark"] {
--bg: #0b0f19;
--text: #e5e7eb;
}
body { background: var(--bg); color: var(--text); }
Pair that with @media (prefers-color-scheme: dark) so first-time visitors get the mode their system already asked for, and store an explicit choice in localStorage for people who override it.
Common questions
Should I still use a CSS framework?
Frameworks save time on large projects with several contributors, mostly by enforcing consistency. For a small site, native grid and flexbox plus custom properties cover nearly everything, and ship less code.
Why does my layout break only on iPhone?
Usually the dynamic viewport. Use the dvh unit instead of vh for full-height sections, because the browser chrome changes the visible height as the page scrolls.
Keep reading
HTML Basics: The Elements Every Page Uses
A practical introduction to HTML structure, the elements you use every day, forms, and the accessibility habits that keep pages working.
Web Performance: What Actually Makes Pages Fast
Core Web Vitals in plain language, the handful of changes that produce most of the speed gain, and how to measure improvement honestly.
Deploying a Static Site: From Folder to Live URL
How static hosting works, deploying with GitHub Pages and the main alternatives, connecting a custom domain, HTTPS, and what to check after launch.
Spotted something out of date? Send a correction — guides are revised rather than quietly deleted.