CSS · Lesson 7

Flexbox: Container

Lining things up in a row or a column

Menus, toolbars and rows of cards are everywhere on the web. Flexbox is the CSS tool that lines them up neatly with just a few lines.

What you'll learn

  • How display: flex puts the children of a box in a row.
  • How to spread items out and line them up with justify-content and align-items.
  • How to switch to a column, let items wrap onto new lines, and add gaps.

Let's line things up

Flexbox is a way to lay out the children of one box. You add display: flex; to the parent, called the flex container. Its children, called flex items, line up in a row. Then a few properties on the container decide how the items spread out and line up.

Think of books on a shelf. The shelf is the flex container, and the books are the items. They stand side by side in a row. You can push them to one end or spread them across the shelf (justify-content). Tall and short books all stand on the shelf's bottom (align-items). When one shelf is full, the next books go on the shelf below (flex-wrap).

A flex container has two directions. The main axis is the way the items line up: left to right in a row. The cross axis goes the other way: up and down. justify-content works along the main axis, and align-items works along the cross axis.

A closer look

justify-content: spreading items along the row

Each box below is a flex container with three items. Only justify-content changes.

align-items: lining items up and down

Here the three items have different heights. Only align-items changes.

Rows or columns: flex-direction

flex-direction: row; is the default. flex-direction: column; stacks the items from top to bottom instead. In a column, the main axis goes down, so justify-content moves items up and down, and align-items moves them left and right.

When items don't fit: flex-wrap

By default, all items stay on one line and shrink to fit. flex-wrap: wrap; lets them keep their size and move to a new line instead, like books going onto the next shelf. When items wrap onto several lines inside a tall container, align-content moves those lines up or down, or spreads them out.

Space between items: gap

gap: 12px; on the container adds 12 pixels between the items, and between the lines when they wrap. Unlike margin, it adds no extra space at the outer edges.

Let's build it

Let's lay out the Front Page Bytes top bar and a row of category cards. Each code box opens on the CSS tab with the new lines highlighted. Click HTML to see the page being styled.

Step 1: Turn on flexbox

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}
What you see

Before this step, the logo and the links were on separate lines, because the links sit in a <div>. display: flex; on .topbar puts its two children, the logo and the links box, side by side.

Step 2: Push them apart

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}
What you see

justify-content: space-between; puts the first item at the left edge and the last one at the right edge. This is a very common top bar layout.

Step 3: Line them up in the middle

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}
What you see

The logo is bigger than the links, so they didn't line up. align-items: center; puts both in the middle, up and down.

Step 4: Put the cards in a row

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}.cards {  display: flex;  gap: 12px;  margin-top: 16px;}
What you see

A second flex container: .cards. Its five cards line up in a row, and gap adds 12 pixels between them. Look closely: five cards don't fit in the mini browser, so they shrink to fit.

Step 5: Let the cards wrap

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}.cards {  display: flex;  gap: 12px;  margin-top: 16px;  flex-wrap: wrap;}
What you see

flex-wrap: wrap; lets the cards keep their size. The ones that don't fit move to a new line, and the gap works between the lines too.

Step 6: Center the rows

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}.cards {  display: flex;  gap: 12px;  margin-top: 16px;  flex-wrap: wrap;  justify-content: center;}
What you see

justify-content: center; moves the cards on each line to the middle. On a phone or a computer, the rows stay neat and centered.

Quick notes

display: flex Turn on flexbox
.cards { display: flex; }

How to use

  • display: flex; Goes on the parent. Its children line up in a row.
  • The parent is called the flex container, and its children are the flex items.
  • display: inline-flex; The same, but the container itself sits inside a line of text.

Examples

  1. A top bar with the logo and links in one row.

    .topbar {  display: flex;}
  2. A row of cards.

    .cards {  display: flex;}
flex-direction Row or column
.menu { flex-direction: column; }

How to use

  • row Items go left to right. This is the default.
  • column Items go top to bottom.
  • row-reverse / column-reverse The same directions, in reverse order.

Examples

  1. A menu that goes down the side of the page.

    .side-menu {  display: flex;  flex-direction: column;}
  2. A row of buttons.

    .buttons {  display: flex;  flex-direction: row;}
justify-content Spread along the main axis
.topbar { justify-content: space-between; }

How to use

  • flex-start Items gather at the start. This is the default.
  • center Items gather in the middle.
  • flex-end Items gather at the end.
  • space-between The first and last items touch the edges, and the space is shared between them.
  • space-around / space-evenly Space around every item, or exactly equal gaps everywhere.

Examples

  1. A logo on the left and links on the right.

    .topbar {  display: flex;  justify-content: space-between;}
  2. Buttons in the middle of a box.

    .buttons {  display: flex;  justify-content: center;}
  3. A footer with links spread out evenly.

    .footer {  display: flex;  justify-content: space-evenly;}
align-items Line up along the cross axis
.topbar { align-items: center; }

How to use

  • stretch Items stretch to the full height of the row. This is the default.
  • flex-start Items line up at the top.
  • center Items line up in the middle, up and down.
  • flex-end Items line up at the bottom.

Examples

  1. A big logo and small links lined up in the middle.

    .topbar {  display: flex;  align-items: center;}
  2. Cards of different heights lined up at the top.

    .cards {  display: flex;  align-items: flex-start;}
flex-wrap Move to a new line
.cards { flex-wrap: wrap; }

How to use

  • nowrap All items stay on one line and shrink to fit. This is the default.
  • wrap Items that don't fit move to a new line.

Examples

  1. Cards that move to a new row on small screens.

    .cards {  display: flex;  flex-wrap: wrap;}
  2. Tags under a story that fill as many lines as needed.

    .tags {  display: flex;  flex-wrap: wrap;}
align-content Move the wrapped lines
.cards { align-content: center; }

How to use

  • flex-start / center / flex-end Moves all the lines together, up or down.
  • space-between Shares the extra space between the lines.
  • Only matters when items wrap onto more than one line and the container is taller than the lines.

Examples

  1. Rows of cards in the middle of a tall box.

    .cards {  display: flex;  flex-wrap: wrap;  height: 400px;  align-content: center;}
gap Space between items
.cards { gap: 12px; }

How to use

  • 12px The space between items, in rows and columns.
  • row-gap / column-gap Space between lines only, or between items in a line only.
  • It adds space only between items, not at the edges.

Examples

  1. Space between cards in a row.

    .cards {  display: flex;  gap: 12px;}
  2. More space between rows than between cards.

    .cards {  display: flex;  flex-wrap: wrap;  row-gap: 24px;  column-gap: 12px;}

Common mistakes

These are mistakes many beginners make. Each mini browser shows what really happens.

Putting display: flex on the items

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;  display: flex;}
What you see

display: flex; went on each .card, so it only lines up what's inside each card. The cards themselves are still stacked, one per line.

Tip: Put display: flex; on the parent that holds the items, here .cards.

Using justify-content to center up and down

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  height: 80px;  justify-content: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;}
What you see

The bar is 80 pixels tall, and the plan was to center the items up and down. But in a row, justify-content works left to right, so the items move to the middle of the bar's width and stay at the top.

Tip: In a row, use align-items: center; to center up and down.

Putting gap on the items

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.topbar {  background-color: #11141A;  padding: 12px;  display: flex;  justify-content: space-between;  align-items: center;}.logo {  color: #FFD043;  font-size: 22px;  font-weight: 700;}.links a {  color: white;  margin-left: 12px;}.card {  background-color: white;  border: 3px solid #11141A;  padding: 16px;  width: 110px;  gap: 12px;}.cards {  display: flex;  flex-wrap: wrap;}
What you see

gap sets the space between a container's items. A .card has no flex items of its own, so the gap does nothing and the cards touch each other.

Tip: Put gap on the flex container: .cards { gap: 12px; }

Test your knowledge

Edit the CSS on the left. Open the HTML tab to see the class names you can use. The mini browser updates as you type, and each goal gets a check mark when it's done.

No clicking needed. Each goal gets a check mark by itself once your code does it.

  1. Turn .menu into a flex container. not done yet
  2. Spread the .menu links out with justify-content: space-between. not done yet
  3. Put the .days boxes in a row. not done yet
  4. Let the .days boxes wrap onto new lines. not done yet
  5. Add a gap between the .days boxes. not done yet
Your code
What you see

Go to Exercises

Recap

  • display: flex; goes on the parent. Its children line up along the main axis, in a row by default, or in a column with flex-direction: column;.
  • justify-content spreads items along the main axis, and align-items lines them up along the cross axis.
  • flex-wrap: wrap; moves items that don't fit to a new line, align-content moves those lines, and gap adds space between items.

References

Lesson content prepared by the WebCore F.E. team for beginner learners. The following references were used in preparing this lesson.

  • W3C. CSS Flexible Box Layout Module Level 1 (official specification). Open reference
  • W3C. CSS Box Alignment Module Level 3 (official specification, gap and alignment). Open reference
  • LibreTexts. Web Site Design (2022, open textbook). Open reference