πŸ“
CodingπŸŽ“ Ages 14-18Intermediate 13 min read

CSS Flexbox Basics

A practical teen tutorial on CSS Flexbox: turn a container into a flex container, control direction, justify-content, align-items, gap and flex-grow to build clean, modern layouts, with runnable code and a quiz.

Key takeaways

  • display: flex turns an element into a flex container and its children into flex items
  • flex-direction sets the main axis: row (default) or column
  • justify-content spaces items along the main axis
  • align-items positions items along the cross axis
  • gap adds even spacing between items, and flex: 1 lets items grow to fill space

What problem does Flexbox solve?

Before Flexbox, lining things up in CSS was painful. Centering a box vertically, spacing buttons evenly, or making columns equal height took hacks with floats and margins. Flexbox (the Flexible Box Layout) fixes all of that. It's a layout system designed to arrange items in a single direction β€” a row or a column β€” and distribute space between them intelligently.

The core idea is simple: you mark one element as a flex container, and its direct children automatically become flex items you can align and space with a handful of properties. In this lesson you'll learn the essential ones and build a working navbar and card row. This builds on Styling Web Pages with CSS, so make sure you're comfortable with basic selectors first.

Step 1: Turn on flex

You start by setting display: flex on the container β€” the element that holds the items you want to arrange:

.container {
  display: flex;
}

With HTML like this:

<div class="container">
  <div class="item">A</div>
  <div class="item">B</div>
  <div class="item">C</div>
</div>

The moment you add display: flex, the three boxes line up in a row side by side, instead of stacking on separate lines like normal <div>s do. That's the default behaviour. Everything else is about controlling how they line up.

The two axes

Flexbox thinks in terms of two directions:

  • The main axis β€” the direction items flow along (horizontal by default).
  • The cross axis β€” the direction at 90Β° to it (vertical by default).

This matters because two key properties work on different axes: justify-content works along the main axis, and align-items works along the cross axis. Keep this picture in mind and Flexbox stops feeling random.

Step 2: flex-direction

flex-direction sets which way the main axis points:

.container {
  display: flex;
  flex-direction: row;     /* default: left to right */
}

The four values:

ValueItems flow
rowleft β†’ right (default)
row-reverseright β†’ left
columntop β†’ bottom
column-reversebottom β†’ top

Switching to column instantly stacks the items vertically. Notice that when you change the direction, the main and cross axes swap too β€” so justify-content now works vertically and align-items horizontally.

Step 3: justify-content (main axis)

justify-content controls how items are spaced along the main axis:

.container {
  display: flex;
  justify-content: space-between;
}

The most useful values:

  • flex-start β€” bunched at the start (default).
  • center β€” centered as a group.
  • space-between β€” first and last hug the edges, equal gaps between.
  • space-around β€” equal space around each item.
  • space-evenly β€” perfectly equal gaps everywhere.

space-between is what you'll reach for in a navbar: logo on the left, links on the right.

Step 4: align-items (cross axis)

align-items controls how items line up on the cross axis. In a default row, that's vertical alignment:

.container {
  display: flex;
  align-items: center;   /* vertically center the items */
  height: 200px;
}

Common values:

  • stretch β€” items stretch to fill the container's height (default).
  • center β€” items centered on the cross axis.
  • flex-start / flex-end β€” pinned to the top / bottom.

The famous "how do I center a box both ways?" question is now trivial:

.container {
  display: flex;
  justify-content: center;   /* center horizontally */
  align-items: center;       /* center vertically */
  height: 300px;
}

That's it. One container, two lines, perfectly centered.

Step 5: gap and flex-grow

To put even spacing between items without fiddly margins, use gap:

.container {
  display: flex;
  gap: 16px;   /* 16px between every item */
}

And to let items grow to fill leftover space, give them flex:

.item {
  flex: 1;   /* every item takes an equal share of the free space */
}

If you give one item flex: 2 and the others flex: 1, that one takes twice the share. This is how you make flexible, proportional columns.

A complete worked example

Here's a small page with a navbar and a row of three equal cards, all built with Flexbox. Save it as an .html file and open it in a browser. Resize the window to watch the cards share the space.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Flexbox Demo</title>
  <style>
    body { font-family: sans-serif; margin: 0; }

    /* Navbar: logo left, links right, vertically centered */
    .navbar {
      display: flex;
      justify-content: space-between;
      align-items: center;
      background: #1e293b;
      color: white;
      padding: 16px 24px;
    }
    .links {
      display: flex;
      gap: 20px;
    }

    /* Card row: three equal, growing cards */
    .cards {
      display: flex;
      gap: 16px;
      padding: 24px;
    }
    .card {
      flex: 1;                 /* equal share of the space */
      background: #e0f2fe;
      border-radius: 10px;
      padding: 20px;
      text-align: center;
    }
  </style>
</head>
<body>
  <nav class="navbar">
    <strong>MySite</strong>
    <div class="links">
      <span>Home</span>
      <span>About</span>
      <span>Contact</span>
    </div>
  </nav>

  <div class="cards">
    <div class="card"><h2>Fast</h2><p>Loads instantly.</p></div>
    <div class="card"><h2>Simple</h2><p>Easy to use.</p></div>
    <div class="card"><h2>Modern</h2><p>Built with Flexbox.</p></div>
  </div>
</body>
</html>

Reading the result:

  • The navbar uses justify-content: space-between to push the logo and links apart, and align-items: center to line them up vertically.
  • The cards each have flex: 1, so they share the row equally and resize as the window changes.
  • The gap keeps clean spacing without a single margin.

Try it yourself

  1. Reverse it. Add flex-direction: row-reverse to .links and watch the menu order flip.
  2. Make one card bigger. Give the middle card flex: 2 and the others flex: 1, then see how the space is divided.
  3. Stack on small screens. Add flex-wrap: wrap and a min-width: 200px to .card so the cards drop onto a new line when the window gets narrow.

Challenge: Build a profile card that's perfectly centered in the middle of the screen. Use a full-height container (height: 100vh) with display: flex; justify-content: center; align-items: center;, and inside it place a card containing an emoji avatar, a name and a short bio laid out in a flex-direction: column. Once it works, make it responsive using the ideas in Responsive Web Design Basics.

Quick quiz

Test yourself and earn XP

What property turns an element into a flex container?

What does flex-direction: column do?

Which property spreads items out along the main axis?

How do you make a flex item grow to share leftover space?

What does justify-content: center do in a default row?

FAQ

Flexbox is best for laying things out in a single direction β€” a row of buttons, a navbar, or a column of cards. CSS Grid is better when you need rows AND columns at the same time, like a full page layout. Many sites use both: Grid for the page skeleton, Flexbox inside each section.

The most common reason is putting justify-content or align-items on the wrong element. They belong on the flex CONTAINER (the parent with display: flex), not on the children. Also check that the items are direct children β€” flex only affects one level down.