Contact, if you are interested in this website / domain name / Sponsorship / Advertisement / Partnership
HomeLearnToolsRoadmapVideosBuildSponsorshipAboutContactStart a project
Beginner

CSS Layout: Flexbox and Grid Without the Guesswork

10 minute read · Last updated 2026-10-31 · Written and reviewed by the Code.House editorial team

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() and clamp() — 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: 70ch on body text. Measured in characters, it keeps lines at a comfortable reading length regardless of font size.
  • aspect-ratio: 16 / 9 on 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

Spotted something out of date? Send a correction — guides are revised rather than quietly deleted.