Chapter 16: Layout with Flexbox

Flexbox fundamentals: direction, wrapping, alignment, flex sizing, gap, and practical patterns

Dania Rifki

Dania Rifki

Table of content
  1. The basics
  2. Direction
  3. Wrapping
  4. Alignment
  5. Flex sizing
  6. The gap property
  7. A practical pattern: the cluster

Flexbox is a CSS layout system designed for distributing items along a single axis. Think of it as laying items out in a row or a column, with fine control over alignment, spacing, and wrapping.

The basics

Apply display: flex to a container, and its direct children become flex items:

.nav-links {
  display: flex;
  gap: var(--space-s);
}
<nav>
  <div class="nav-links">
    <a href="/work">Work</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
  </div>
</nav>

By default, flex items line up in a row and don't wrap. If the container is too narrow, they'll squish.

An interactive playground where you can toggle flex-direction, flex-wrap, and justify-content and watch items rearrange in real time. Also includes the resizable sidebar layout pattern. (Uses JavaScript for the interactive controls.)

Direction

/* Row (default): items flow left to right */
.row { display: flex; flex-direction: row; }

/* Column: items stack top to bottom */
.column { display: flex; flex-direction: column; }

Wrapping

This is where flexbox becomes powerful for fluid design. flex-wrap: wrap allows items to move to a new line when they run out of space:

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}
<ul class="tag-list">
  <li>Oil painting</li>
  <li>Watercolor</li>
  <li>Digital</li>
  <li>Charcoal</li>
  <li>Mixed media</li>
</ul>

On a wide screen, all tags sit on one line. As the screen narrows, they naturally wrap to multiple lines. No breakpoints needed.

Alignment

Flexbox gives you two axes of alignment:

.centered {
  display: flex;
  justify-content: center;  /* align along the main axis (horizontal for rows) */
  align-items: center;      /* align along the cross axis (vertical for rows) */
}

Common justify-content values:

Common align-items values:

Flex sizing

Individual flex items can control how they grow, shrink, and what their base size is. The three properties involved are:

Here's how these properties work together in practice:

.sidebar-layout {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-l);
}

.sidebar-layout > :first-child {
  flex-basis: 15rem;   /* ideal starting width */
  flex-grow: 1;        /* can grow */
}

.sidebar-layout > :last-child {
  flex-basis: 0;
  flex-grow: 999;      /* grows much more than the sidebar */
  min-width: 60%;      /* if it can't get 60%, it wraps to its own line */
}

This creates a sidebar layout that automatically stacks on narrow screens without any breakpoints. When there isn't enough room for both the sidebar and the main content side by side, the main content wraps to its own line. This is an example of an intrinsic layout: the content itself decides when to reflow.

The gap property

gap sets the spacing between flex items (and works in Grid too):

.nav-links {
  display: flex;
  gap: var(--space-s);
}

It's cleaner than adding margins to individual items, and it only adds space between items, not at the edges.

A practical pattern: the cluster

A "cluster" is a flex layout for groups of items that should wrap freely, like tags, social links, or navigation:

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  align-items: center;
}

This single utility handles navigation bars, tag lists, icon groups, footer links, and more. Simple and endlessly reusable.

For a deeper mental model of how Flexbox works, Josh Comeau's An Interactive Guide to Flexbox walks through every property with live, interactive examples that make the layout model click. If you prefer a more hands-on and playful approach, Flexbox Froggy teaches the same concepts through a series of small puzzles.