Quick Answer

Flexbox is a CSS layout system for arranging elements in a single row or column. You turn any element into a flex container with display: flex, then use properties like justify-content and align-items to position its children along the main and cross axes. It handles spacing, alignment, and wrapping with very little code, which makes it ideal for navbars, button groups, and card rows.

What this CSS Flexbox tutorial covers

If you have ever fought with float or stacked a dozen margin hacks just to line up a few boxes, this CSS Flexbox tutorial is for you. Flexbox, short for the Flexible Box Layout, is a layout system built into CSS that arranges elements in one direction — a row or a column — and gives you clean control over spacing and alignment with very little code.

Before Flexbox, developers leaned on floats, tables, and inline-block tricks that were fragile and hard to read. Flexbox replaced most of that. It shines for one-dimensional layouts: a single row or a single column. When you need full two-dimensional control (rows and columns at the same time), CSS Grid is the better tool. But for navbars, toolbars, button groups, and card rows, Flexbox is usually all you need.

By the end you will understand the container and item roles, the main and cross axes, the core properties, and you will have built two real components: a responsive navbar and a row of cards that wraps on small screens. Everything here is plain CSS with no framework. If you want the full picture afterwards, our free CSS course walks through layout step by step.

The flex container vs the flex items

Flexbox always involves two roles. The flex container is the parent element you switch Flexbox on. The flex items are its direct children, which the container then arranges. This split matters because some properties belong on the container and others belong on the items.

You create a container by setting display: flex on it:

<div class="container">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>
.container {
  display: flex;
}

The moment you add that one line, the three inner <div> elements stop stacking vertically and line up in a row. They became flex items automatically because they are direct children.

Two things to remember. First, only direct children become flex items — grandchildren are not affected unless you also make their parent a flex container. Second, display: flex makes a block-level container; if you want the container itself to sit inline with surrounding text, use display: inline-flex instead.

The main axis and the cross axis

This is the single most important idea in Flexbox. Every flex container has two axes: the main axis and the cross axis. Items are laid out along the main axis, and the cross axis runs perpendicular to it.

Which direction each axis points depends on flex-direction:

SettingMain axis runsCross axis runs
flex-direction: row (default)Left to rightTop to bottom
flex-direction: columnTop to bottomLeft to right

Why does this matter? Because the two most-used alignment properties each work on a different axis:

  • justify-content aligns items along the main axis.
  • align-items aligns items along the cross axis.

So with the default row direction, justify-content moves items left and right, while align-items moves them up and down. Switch to column and those roles flip. Beginners often set the wrong property and wonder why nothing moves — keeping the axes straight in your head fixes most of that confusion.

The key Flexbox properties

Here are the properties you will reach for constantly. Notice that most of them live on the container, and only flex lives on the items.

PropertySet onWhat it does
display: flexContainerTurns Flexbox on
flex-directionContainerRow or column; sets the main axis
justify-contentContainerAligns items along the main axis
align-itemsContainerAligns items along the cross axis
gapContainerAdds space between items
flex-wrapContainerLets items wrap onto new lines
flexItemHow an item grows, shrinks, and its base size

The common justify-content values are flex-start, center, flex-end, space-between, space-around, and space-evenly. For align-items you will mostly use stretch (the default), center, flex-start, and flex-end.

A quick word on gap: it is the clean, modern way to space items out. In the past people added margins to every item and then removed the margin from the last one. With gap: 1rem the browser handles the spacing between items for you, and it is well supported in every current browser.

Build a responsive navbar

Time to build something real. A navbar is the classic Flexbox job: a logo on the left, some links on the right, everything vertically centred. Here is the markup:

<nav class="navbar">
  <a class="logo" href="/">Priodemy</a>
  <ul class="links">
    <li><a href="/courses">Courses</a></li>
    <li><a href="/blog">Blog</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

And the CSS. Notice we use Flexbox twice: once on the whole navbar, and once on the list of links.

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
}

.links {
  display: flex;
  gap: 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

Let us read it out loud. On .navbar, justify-content: space-between pushes the logo to the far left and the link list to the far right along the main axis, with all the free space between them. align-items: center lines them up vertically on the cross axis so the logo and links share the same middle line even if their heights differ. On .links, a second display: flex turns the vertical list into a horizontal row, and gap: 1.5rem spaces the links evenly. That is a complete, working navbar in about a dozen lines.

Build a responsive row of cards

Now a row of cards that stays neat on a wide screen and wraps gracefully on a phone. The key ingredients are flex-wrap on the container and the flex shorthand on each item.

<div class="cards">
  <div class="card">Card one</div>
  <div class="card">Card two</div>
  <div class="card">Card three</div>
  <div class="card">Card four</div>
</div>
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.card {
  flex: 1 1 250px;
  padding: 1rem;
}

The magic line is flex: 1 1 250px. That shorthand sets three things at once: flex-grow: 1 (each card can grow to fill spare space), flex-shrink: 1 (each card can shrink if needed), and flex-basis: 250px (each card wants to be about 250px wide before growing or shrinking).

Combined with flex-wrap: wrap, this gives you responsive behaviour with no media queries. On a wide screen you might get four cards in a row; as the window narrows, the cards shrink, then wrap to two per row, then to one per row on a phone. The cards always fill the available width evenly. This pattern — a wrapping flex row with a sensible flex-basis — covers a huge share of real-world grids.

Common gotchas to avoid

A few things trip up almost every beginner. Knowing them in advance saves hours.

  • align-items looks like it does nothing. On a single row of short items, everything is already the same height, so centring on the cross axis has no visible effect. Give the container a height, or put items of different heights inside, and you will see it work.
  • You set the property on the wrong element. justify-content, align-items, and flex-wrap go on the container. flex goes on the item. Putting justify-content on a child does nothing.
  • Confusing the two axes. After you set flex-direction: column, justify-content now controls vertical position and align-items controls horizontal position. Re-check which axis is which whenever you change direction.
  • Reaching for Flexbox when you need Grid. Flexbox is one-dimensional. If you truly need aligned rows and columns, like a photo gallery or a dashboard, CSS Grid will be simpler.
  • Forgetting list resets. When you flex a <ul>, remember to remove its default list-style, margin, and padding, as we did in the navbar.

Recommendation and next steps

Our advice: reach for Flexbox as your default for any single row or column of elements. It is well supported across all modern browsers, it needs very little code, and it removes the fragile float and margin hacks of the past. Save CSS Grid for genuine two-dimensional layouts and let the two tools complement each other — they are designed to work together, and it is normal to nest a flex container inside a grid cell or vice versa.

The fastest way to learn is to build. Recreate the navbar and the card row above, then change one value at a time and watch what happens. Swap space-between for center, flip flex-direction to column, or change the flex-basis on the cards. That hands-on tinkering is what makes the axes click.

When you are ready to go further — positioning, responsive design, transitions, and full page layouts — the free Priodemy CSS course takes you from the basics to production-ready pages, with exercises at every step.

Frequently Asked Questions

When should I use Flexbox instead of CSS Grid?

Use Flexbox for one-dimensional layouts — a single row or a single column, like a navbar, a button group, or a wrapping row of cards. Use CSS Grid when you need to control rows and columns at the same time, like a photo gallery or a dashboard. They work well together, so it is common to nest a flex container inside a grid cell.

How do I perfectly center an element with Flexbox?

Set three properties on the parent container: display: flex, justify-content: center, and align-items: center. That centres the child on both the main and cross axes. Make sure the container has enough height for the vertical centring to be visible, otherwise the item is already as tall as its content and nothing appears to move.

Why is align-items not doing anything?

Usually because all the items are already the same height, so there is no spare room on the cross axis to align within. Give the container a fixed or minimum height, or place items of differing heights inside it, and the effect becomes visible. Also double-check you put align-items on the container, not on a child item.

What does flex: 1 1 250px actually mean?

It is shorthand for three properties on a flex item: flex-grow: 1 (the item can grow to fill extra space), flex-shrink: 1 (it can shrink when space is tight), and flex-basis: 250px (its ideal starting size). Together with flex-wrap: wrap on the container, this creates responsive cards that grow, shrink, and wrap without media queries.

Is Flexbox supported in all browsers?

Yes. Flexbox is supported in every current version of Chrome, Firefox, Safari, and Edge on both desktop and mobile, so you can use it in production without prefixes for modern audiences. The gap property in Flexbox is also widely supported today, which lets you drop the old margin-based spacing tricks.

What is the difference between the main axis and the cross axis?

The main axis is the direction items flow in, set by flex-direction — horizontal for row and vertical for column. The cross axis runs perpendicular to it. justify-content aligns items along the main axis, and align-items aligns them along the cross axis, so switching the direction swaps which property controls horizontal versus vertical.