Skip to content
Educora
Advanced20 min8 / 10

Flexbox: laying things out in a line

Use Flexbox to line elements up in a row or column, share the space between them, center them and let them adapt to the space available.

Check yourself
In this lesson you will learn
  • Create a flex container and explain the main and cross axes
  • Align items with justify-content, align-items and gap
  • Center an element in both directions
  • Build flexible menus and card rows with flex, flex-wrap and margin-left: auto

At the top of almost every website you see the same picture: the logo on the left, the menu on the right, all on one line and vertically centered. For years, centering something vertically was a famous headache for web developers. Flexbox solves it in a few lines.

The flex container and its axes

When you give a parent display: flex, it becomes a flex container and its direct children become flex items. The items line up along the main axis: by default a horizontal line from left to right (flex-direction: row). The axis perpendicular to it is the cross axis. If you write flex-direction: column, the axes swap: the items line up from top to bottom.

HTML
<style>
  body { font-family: system-ui, sans-serif; padding: 12px; }
  .box { padding: 8px; margin-bottom: 12px; background: #f1f5f9; border-radius: 8px; }
  .flex { display: flex; gap: 8px; }
  .item { padding: 10px 16px; background: #818cf8; color: white; border-radius: 6px; }
</style>

<p>Without flex: blocks stack.</p>
<div class="box">
  <div class="item">1</div><div class="item">2</div><div class="item">3</div>
</div>

<p>With display: flex: one row.</p>
<div class="box flex">
  <div class="item">1</div><div class="item">2</div><div class="item">3</div>
</div>
Preview
Add flex-direction: column; to the .flex rule — the items stack again, but the gap between them stays.

Alignment: `justify-content` and `align-items`

justify-content places items along the main axis and distributes the free space. align-items aligns them on the cross axis. Both properties go on the container, not on the items.

HTML
<style>
  body { font-family: system-ui, sans-serif; padding: 8px; font-size: 13px; }
  .row { display: flex; margin: 2px 0 8px; background: #f1f5f9; border-radius: 6px; }
  .row div { width: 40px; margin: 3px; padding: 4px 0; text-align: center;
             background: #34d399; border-radius: 4px; }
  .start { justify-content: flex-start; }
  .center { justify-content: center; }
  .end { justify-content: flex-end; }
  .between { justify-content: space-between; }
  .evenly { justify-content: space-evenly; }
</style>

<code>flex-start</code><div class="row start"><div>1</div><div>2</div><div>3</div></div>
<code>center</code><div class="row center"><div>1</div><div>2</div><div>3</div></div>
<code>flex-end</code><div class="row end"><div>1</div><div>2</div><div>3</div></div>
<code>space-between</code><div class="row between"><div>1</div><div>2</div><div>3</div></div>
<code>space-evenly</code><div class="row evenly"><div>1</div><div>2</div><div>3</div></div>
Preview
space-between pushes the outer items to the edges, while space-evenly makes every gap equal. Try space-around on one .row and spot the difference.
PropertyValuesWhat it does
flex-directionrow, columndirection of the main axis
justify-contentflex-start, center, space-between…placement along the main axis
align-itemsstretch, center, flex-start, flex-endalignment on the cross axis (default stretch)
flex-wrapnowrap, wrapmoving to a new line when space runs out
gap8px, 1rem…space between items
All of these properties are set on the flex container.
HTML
<style>
  body { font-family: system-ui, sans-serif; padding: 12px; }
  .stage {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 180px;
    background: linear-gradient(135deg, #a5b4fc, #f9a8d4);
    border-radius: 12px;
  }
  .badge { padding: 14px 22px; background: white; border-radius: 10px; font-weight: 700; }
</style>

<div class="stage">
  <div class="badge">Perfectly centered 🎯</div>
</div>
Preview
Change align-items to flex-end, then to flex-start. linear-gradient is a background that blends smoothly between two colors.

Flexible sizes: `flex` and `flex-wrap`

The “flex” in Flexbox means that items can grow and shrink to fit the free space. The flex property on an item controls this. flex: 1 tells an item: “take all the remaining space”. If several items all have flex: 1, they share the free space equally. The full form flex: 1 1 140px has three values: grow (flex-grow), shrink (flex-shrink) and starting size (flex-basis).

HTML
<style>
  body { font-family: system-ui, sans-serif; margin: 0; }
  nav { display: flex; align-items: center; gap: 16px; padding: 12px 16px; background: #1e293b; }
  nav a { color: #e2e8f0; text-decoration: none; }
  .logo { font-weight: 800; color: #fbbf24; }
  .login { margin-left: auto; padding: 6px 14px; background: #fbbf24; color: #1e293b; border-radius: 6px; }
  .page { display: flex; gap: 12px; padding: 12px; }
  .side { width: 110px; padding: 10px; background: #e0e7ff; border-radius: 8px; }
  .content { flex: 1; padding: 10px; background: #f1f5f9; border-radius: 8px; }
</style>

<nav>
  <span class="logo">MySite</span>
  <a href="#">Home</a>
  <a href="#">Blog</a>
  <a href="#" class="login">Log in</a>
</nav>
<div class="page">
  <aside class="side">Side menu: 110px</aside>
  <main class="content">flex: 1 takes all the space that is left.</main>
</div>
Preview
In the menu, .login is pushed to the right because margin-left: auto gathers all the free space on its left. Give .side flex: 1 too — the two columns become equal.

By default flex items stay on one line and shrink when needed. flex-wrap: wrap lets them move to a new line when there isn't enough room. Combined with flex: 1 1 140px, it gives you a row of cards that looks good on a phone and on a wide screen.

HTML
<style>
  body { font-family: system-ui, sans-serif; padding: 12px; background: #f8fafc; }
  .cards { display: flex; flex-wrap: wrap; gap: 12px; }
  .card { flex: 1 1 140px; padding: 12px; text-align: center;
          background: white; border: 1px solid #e2e8f0; border-radius: 10px; }
  .card span { font-size: 32px; }
  .card p { margin: 6px 0 0; }
</style>

<div class="cards">
  <div class="card"><span>🍎</span><p>Apples</p></div>
  <div class="card"><span>🍐</span><p>Pears</p></div>
  <div class="card"><span>🍇</span><p>Grapes</p></div>
  <div class="card"><span>🍑</span><p>Peaches</p></div>
  <div class="card"><span>🍋</span><p>Lemons</p></div>
</div>
Preview
Change 140px to 250px — fewer cards fit on a line and the rest wrap. Then remove flex-wrap: wrap and watch the cards squeeze together.

Key points

  • display: flex turns a container into a flex container and its direct children into flex items.
  • flex-direction picks the main axis: row is horizontal, column is vertical.
  • justify-content aligns on the main axis, align-items on the cross axis; gap adds space between items.
  • flex: 1 makes an item take the remaining space; flex-wrap: wrap lets items move to a new line.
  • Centering: justify-content: center + align-items: center; pushing an item to the end: margin-left: auto.

Check yourself

10 questions. Every correct answer earns XP.

1 / 10
Which rule turns an element into a flex container?