Flexbox: Lining Things Up in a Row or a Column

One line of CSS, display: flex, lines up an element's children in a row, flex-direction turns the row into a column, and the main and cross axes name the two directions every other flexbox property works along.

Apprentice · CSS · Updated

After this lesson you can

  • Make a flex container with display: flex and set its direction with flex-direction
  • Name the main axis and the cross axis of a flex container in a row or a column

Key takeaways

  • display: flex goes on the parent. The parent becomes a flex container, and only its direct children become flex items.
  • Flex items line up in a row by default, each as wide as its content and stretched to the height of the row.
  • flex-direction: column stacks the items top to bottom. Without display: flex, flex-direction does nothing.
  • The main axis is the direction the items run in. The cross axis runs across it. In a column the two swap.

Look at the top of almost any website: a logo, then a row of links, all on one line. Under a video there's a row of buttons. On a phone, the menu opens as a column of links. Every one of those is a set of boxes lined up in one direction, and the tool that lines them up is flexbox. You'll use it on nearly every page you build, and "make these sit side by side" is one of the first layout jobs anyone gets.

This chapter builds the website for Summer Sound, a made-up three-day music festival in a riverside park: a nav bar across the top, a big welcome in the middle of the screen, and a row of cards for the bands that rearranges itself on a phone. This lesson starts with the nav bar.

Without flexbox, boxes stack

Here's the festival's menu: a list of links, as most sites write their menus.

<ul class="nav-links">
  <li><a href="lineup.html">Lineup</a></li>
  <li><a href="tickets.html">Tickets</a></li>
  <li><a href="map.html">Map</a></li>
  <li><a href="faq.html">FAQ</a></li>
</ul>

Each <li> (a list item) is a block: it takes the whole width of the page, and the next one starts underneath it. So the four links come out as a bulleted column, one per line, which is fine for a shopping list and wrong for a nav bar. That stacking is the browser's normal flow, and Normal Flow and the display Property goes into it. To change it, you change how the list lays out its children.

Before and after: the festival's four menu links stacked as a bulleted list, one per line, and the same four links side by side in one row after display: flex

display: flex turns a parent into a shelf

Think of a bookshelf. The shelf decides how the books line up: side by side, left to right. The books don't arrange themselves; they stand where the shelf puts them.

Flexbox works the same way. You put one line on the parent, and it lines up its children:

.nav-links {
  display: flex;
  list-style: none;
  padding: 0;
}
  • display: flex makes .nav-links a flex container: the shelf.
  • Its direct children, the four <li> elements, become flex items: the books. They now sit side by side in one row, in the order they're written in the HTML.
  • Only direct children become flex items. The <a> inside each <li> is a grandchild, so it's still an ordinary link inside its item.
  • list-style: none and padding: 0 have nothing to do with flexbox: they take away the bullets and the indent a list has by default, because a nav bar doesn't need them.

Each flex item is only as wide as its content: "FAQ" takes less room than "Tickets". And all of them are stretched to the same height, the height of the tallest one. You'll see why in a moment.

Try it. Make a folder named summer-sound with two files. In index.html, put this page:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Summer Sound 2027</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <ul class="nav-links">
    <li><a href="lineup.html">Lineup</a></li>
    <li><a href="tickets.html">Tickets</a></li>
    <li><a href="map.html">Map</a></li>
    <li><a href="faq.html">FAQ</a></li>
  </ul>
</body>
</html>

Open it with Live Server: four bulleted links, one per line. Now put the .nav-links rule above in styles.css, plus .nav-links li { margin-right: 1.5rem; } to give the links some room, and save. The links jump into a row.

A row or a column: flex-direction

A shelf can also stand on its end, like a tall, narrow bookcase where the books are stacked one above the other. The property that turns the shelf is flex-direction:

.phone-menu {
  display: flex;
  flex-direction: column;
}
Value The items run Use it for
row left to right (the default) nav bars, toolbars, a row of buttons
column top to bottom a phone menu, a sidebar of links, a card's title, picture and text
row-reverse right to left rarely: see the note below
column-reverse bottom to top rarely

Two things to know:

  • flex-direction only works on a flex container. On an element without display: flex, the browser ignores it, and the children keep stacking the normal way.
  • The reverse values only change what the eye sees. A screen reader and the Tab key still go through the items in the HTML's order, so reversing a menu makes the keyboard jump backward through it. Flexbox Wrapping and gap explains this when it covers order. If you want the items the other way round, change the order in the HTML instead.

Try it. Add flex-direction: column; to your .nav-links rule and save: the links stack again, this time as flex items with no bullets. Change it to row-reverse: FAQ jumps to the front. Put it back to row when you're done.

The main axis and the cross axis

Back to the shelf. There's the direction the books run along the shelf, and the direction across it, from the bottom of a book to its top. Flexbox gives those two directions names, and every other flexbox property is named for one of them:

  • The main axis is the direction the items run in. flex-direction sets it.
  • The cross axis runs across the main axis, at a right angle to it.
flex-direction Main axis (the way items run) Cross axis (across them)
row left to right: horizontal top to bottom: vertical
column top to bottom: vertical left to right: horizontal

The second row is the one that catches people out: in a column, the main axis is vertical. When you turn the shelf, both axes turn with it.

Here's where the axes already show. By default, flex items stretch along the cross axis to fill the container:

.phone-menu {
  display: flex;
  flex-direction: column;
  width: 300px;
}

In this column the cross axis is horizontal, so each item stretches to the full 300 pixels of the menu, however short its text. In the row nav bar from before, the cross axis is vertical, so the items stretched to the height of the tallest one. Same rule, different direction.

The next lesson, Flexbox Alignment: justify-content and align-items, puts the axes to work: one property spaces the items along the main axis, and another lines them up across it.

Two diagrams side by side: in a row, an arrow labeled main axis runs left to right through the items and an arrow labeled cross axis runs top to bottom; in a column, the main axis arrow runs top to bottom and the cross axis arrow runs left to right

See it in the developer tools

Right-click the nav bar and choose Inspect. In Chrome and Edge, the Elements panel shows a small flex badge next to <ul class="nav-links">: it marks a flex container. Click the badge, and the page draws an outline around each flex item, with the space between them shaded. Firefox shows the same kind of badge in its Inspector, and its Layout panel has a Flexbox section that names each flex item.

Try it. With the overlay on, switch flex-direction between row and column in the Styles pane (Firefox: Rules) and watch the outlines turn. The badge only appears on elements with display: flex, so it's also a quick way to check whether your rule took effect.

Try it in Flex Freight

Flex Freight, puzzles 1 to 4: played right on the lesson page.

Now move some real crates. In Flex Freight the loading dock is a flex container and the crates are its flex items, so display: flex and flex-direction line them up on the spots painted on the dock. The dock changes as you type, and the first puzzle opens with a guide that shows every value before you start.

Check yourself

2 questions to try on the lesson page.

So what

Nav bars, toolbars, button rows, phone menus and card layouts all start as a row or a column of boxes, and two lines on the parent, display: flex and flex-direction, give you either one. Knowing which way the main axis runs is what makes the rest of flexbox make sense.

Key terms

Cheat sheets

Related