Skip to main content
HTML & CSS Foundations·Lesson 3 of 5

Flexbox Layout

Flexbox is a one-dimensional layout system — it arranges items in a single row or column. It excels at distributing space, aligning items, and handling dynamic content sizes.

Enabling Flexbox

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

.row {
  display: flex;
}
<div class="row">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</div>

By default, flex items sit in a row, don't wrap, and stretch to the container's height.

Direction and Wrapping

Control the flow direction and whether items wrap to new lines:

/* Horizontal row (default) */
.row {
  display: flex;
  flex-direction: row;
}

/* Vertical column */
.column {
  display: flex;
  flex-direction: column;
}

/* Allow items to wrap when they run out of space */
.wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

When flex-wrap: wrap is set, items that don't fit on one line move to the next. Without it, items shrink to fit.

Alignment

Flexbox has two axes: the main axis (direction of flow) and the cross axis (perpendicular). Alignment properties work along these axes.

.center-both {
  display: flex;
  justify-content: center; /* main axis */
  align-items: center;     /* cross axis */
  min-height: 100dvh;
}

justify-content (main axis)

.container {
  display: flex;
  /* flex-start | center | flex-end | space-between | space-around | space-evenly */
  justify-content: space-between;
}
  • space-between — equal gaps between items, no gap at edges.
  • space-evenly — equal gaps everywhere, including edges.

align-items (cross axis)

.container {
  display: flex;
  /* stretch | flex-start | center | flex-end | baseline */
  align-items: center;
}
  • stretch (default) — items fill the container's cross-axis size.
  • baseline — items align by their text baselines (useful for mixed font sizes).

Individual item alignment

Override alignment for a single item with align-self:

.container {
  display: flex;
  align-items: flex-start;
}

.container .special {
  align-self: flex-end;
}

Gap

The gap property adds space between flex items without affecting the edges:

.row {
  display: flex;
  gap: 1rem;        /* equal gap in both directions */
}

.grid-like {
  display: flex;
  flex-wrap: wrap;
  row-gap: 1.5rem;
  column-gap: 1rem;
}

This replaces the old technique of adding margins to items and removing the margin from the last one.

Flex Items: grow, shrink, basis

These three properties control how items share available space:

.item {
  flex-grow: 0;    /* don't grow beyond basis (default) */
  flex-shrink: 1;  /* shrink if needed (default) */
  flex-basis: auto; /* start at content width (default) */
}

/* Shorthand: flex: grow shrink basis */
.item {
  flex: 0 1 auto; /* default behavior */
}

Common patterns:

/* Item takes all available space */
.fill {
  flex: 1; /* same as flex: 1 1 0% */
}

/* Item doesn't grow or shrink — fixed size */
.fixed {
  flex: none; /* same as flex: 0 0 auto */
}

/* Two items split space equally */
.half {
  flex: 1 1 0%;
}

Common Flexbox Patterns

<nav class="navbar">
  <a href="/" class="logo">MySite</a>
  <div class="nav-links">
    <a href="/about">About</a>
    <a href="/blog">Blog</a>
    <a href="/contact">Contact</a>
  </div>
</nav>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}

.nav-links {
  display: flex;
  gap: 1.5rem;
}
<div class="card">
  <h3>Card Title</h3>
  <p>Some content that varies in length.</p>
  <a href="#" class="card-link">Read more</a>
</div>
.card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  min-height: 250px;
}

.card-link {
  margin-top: auto; /* pushes to the bottom */
}

Centering anything

.center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100dvh;
}

Input with button

<div class="search">
  <input type="text" placeholder="Search...">
  <button>Go</button>
</div>
.search {
  display: flex;
  gap: 0.5rem;
}

.search input {
  flex: 1; /* input takes remaining space */
}

.search button {
  flex: none; /* button stays its natural size */
}

Order

Change visual order without changing HTML order. Use sparingly — it can confuse keyboard navigation:

.first-visually {
  order: -1; /* moves before items with default order: 0 */
}