# Flexbox Alignment: justify-content and align-items

justify-content spaces flex items along the main axis, align-items and align-self line them up across it, the two together center anything both ways, and an auto margin pushes one item to the far end.

Apprentice · CSS · Updated November 1, 2026

## After this lesson you can

- Choose the justify-content value that spaces flex items along the main axis
- Line up flex items across the cross axis with align-items and align-self, and center an item both ways
- Push one flex item away from the others with an auto margin

## Key takeaways

- justify-content goes on the flex container and decides where the leftover space on the main axis goes, so the items sit at the start, the center, the end or spread out.
- align-items lines the items up on the cross axis. Its default, stretch, makes them all as tall as the row; align-self does the same job for one item.
- To center something both ways, give its parent display: flex, justify-content: center, align-items: center, and a height to center in.
- An auto margin takes all the leftover space on its side, so margin-left: auto pushes an item, and every item after it, to the far end.

"Logo on the left, links on the right." "Put the buttons in the middle." "Center this box on the screen." Those three requests come up on nearly every site, from a class project to a company's home page, and "how do I center a div?" has been one of the most-asked web questions for years. With flexbox, each one is a line or two on the container. This lesson builds the top of the *Summer Sound* festival's page: its nav bar, and a welcome message centered in the middle of the screen.

The lesson uses two words from *Flexbox: Lining Things Up in a Row or a Column*: the **main axis** is the direction the flex items run in (left to right in a row, top to bottom in a column), and the **cross axis** runs across it.

## Where the leftover space goes: justify-content

Four friends sit on a park bench built for eight. There's room left over, and they can choose where it goes: all of them squeezed at one end, all in the middle, or spread out with space between them.

Flex items have the same choice. When they don't fill their container, the empty part is the **leftover space** (CSS calls it *free space*), and **`justify-content`** decides where it goes along the main axis:

```css
.nav-links {
  display: flex;
  justify-content: space-between;
}
```

| `justify-content:` | The items | The leftover space |
|---|---|---|
| `flex-start` | packed at the start (the default) | all after the last item |
| `flex-end` | packed at the end | all before the first item |
| `center` | packed in the middle | split between the two ends |
| `space-between` | the first at the start, the last at the end | shared equally between the items, none at the ends |
| `space-around` | spread out | an equal amount on both sides of every item, so the gaps between items are twice the gaps at the ends |
| `space-evenly` | spread out | equal gaps everywhere, the ends included |

Say the bar is 600 pixels wide and holds three 100-pixel links, so 300 pixels are left over. With `center`, 150 pixels go before the first link and 150 after the last. With `space-between`, the links sit at 0, 250 and 500 pixels from the left: two gaps of 150. With `space-evenly`, four equal gaps of 75.

`justify-content` goes on the **container**, like `display: flex`, never on an item. And it only has something to do when there is leftover space: items that already fill the row have none to share.

![Six versions of the same nav bar, one per justify-content value, with the leftover space shaded: flex-start, flex-end, center, space-between, space-around and space-evenly](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/e952a2ee5c294bb2a37c6fbe0bb58c03.webp)

**Try it.** In a `summer-sound` folder, make an `index.html` with the festival's menu, `<ul class="nav-links">` holding four `<li>` links (Lineup, Tickets, Map, FAQ), and link a `styles.css`. Give `.nav-links` the rule above, then try each value from the table and watch the links move.

## In a column, justify-content works top to bottom

`justify-content` follows the main axis, wherever it points. In a column, the main axis is vertical, so `justify-content: center` centers the items **up and down**.

There's a catch: a column container is only as tall as its items, unless you give it a height. With no extra height there's no leftover space, so nothing moves:

```css
.hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 70vh;
}
```

`min-height: 70vh` makes the festival's welcome area at least 70% of the window's height (`vh` stands for *viewport height*: 1vh is 1% of the window's height). Now the container is taller than its content, and `justify-content: center` puts the content in the middle of that height.

## Lining up across: align-items

Line up the friends from the bench for a photo, and someone always asks: line up by your feet, or so your heads are level? That's alignment across the row, and in flexbox it's **`align-items`**. It goes on the container and works along the **cross axis**:

| `align-items:` | Each item, across the main axis |
|---|---|
| `stretch` | stretched to fill the container (the default, when the item has no height of its own) |
| `flex-start` | at the start: the top of a row |
| `flex-end` | at the end: the bottom of a row |
| `center` | in the middle |
| `baseline` | placed so the bottoms of their first lines of text sit on one line, like words on notebook paper |

The festival's header holds the logo, in big letters, and the nav. Without help, the shorter nav sits at the top, beside the logo's larger text. One line centers them on each other:

```css
.site-header {
  display: flex;
  align-items: center;
}
```

`stretch`, the default, is why the items in the last lesson's nav bar all came out as tall as the tallest one. If you give an item its own `height`, it keeps that height instead.

## One item on its own: align-self

Sometimes one item needs a different line from the rest. **`align-self`** goes on that **item** and takes the same values as `align-items`, overriding the container's choice for that one item only.

Each band's card on the festival site starts with a row: the band's photo, its name and genre underneath each other, and a heart button to save the band to your schedule. The text should start at the top, beside the photo, but the heart looks better in the middle:

```css
.band-row {
  display: flex;
  align-items: flex-start;
}

.band-row .save {
  align-self: center;
}
```

Notice there's no `justify-self` in flexbox: along the main axis, the items share the space as a group, so there's nothing for one item to set on its own. To move one item along the main axis, you use an auto margin, below.

## Centering anything both ways

Put the two properties together, and you can center anything. Here's the festival's welcome area, the part of the page people see first (designers call it the **hero**):

```html
<section class="hero">
  <h1>Summer Sound 2027</h1>
  <p>Three days of music by the river. July 16 to 18, Riverside Park.</p>
  <a class="button" href="tickets.html">Get tickets</a>
</section>
```

```css
.hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-height: 70vh;
  text-align: center;
}
```

Read it one axis at a time. This is a column, so the main axis is vertical: `justify-content: center` centers the heading, the dates and the button **up and down** in the 70vh. The cross axis is horizontal: `align-items: center` centers each one **left to right**. `text-align: center` centers the lines of text inside each item, which is a separate job.

For a single box in a row container (a "Sold out" message in the middle of an empty panel, say), the same two lines work without `flex-direction`. The container needs room to center in, so check its height first when something won't move.

![The festival's hero area: the heading, the dates and the Get tickets button stacked in a column and centered both up and down and left to right in a tall band across the page, with arrows showing which property centers which way](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/0bb49ad078ed45cf897b60a5a09882f7.webp)

## Pushing one item away: an auto margin

Back to the festival's header: the logo should sit on the left and the menu on the right. Picture a spring between them that pushes them as far apart as they can go. That spring is an **auto margin**:

```html
<header class="site-header">
  <a class="logo" href="index.html">Summer Sound</a>
  <nav>
    <ul class="nav-links">
      <li><a href="lineup.html">Lineup</a></li>
      <li><a href="tickets.html">Tickets</a></li>
    </ul>
  </nav>
</header>
```

```css
.site-header nav {
  margin-left: auto;
}
```

In a flex container, a margin of `auto` takes **all** the leftover space on its side. `margin-left: auto` on the `<nav>` fills the space to its left, so the nav moves to the far right and the logo stays on the left. The `<nav>` is the flex item here, because it's the header's direct child; the `<ul>` inside it is its own flex container, which lines up the links.

Why not `justify-content: space-between`? With two items, it does the same. But add a third item, a **Get tickets** button after the nav, and `space-between` puts the nav in the middle and the button on the right. The auto margin pushes the nav **and everything after it** to the right, together, which is what a nav bar usually wants. An auto margin also wins over `justify-content`: it takes the leftover space first, so there's none left for `justify-content` to share.

| You write | It pushes |
|---|---|
| `margin-left: auto` on an item | that item, and the ones after it, to the end of a row |
| `margin-right: auto` on an item | the items after it to the end, leaving it at the start |
| `margin-top: auto` on an item in a column | that item, and the ones after it, to the bottom |
| `margin: auto` on the only item | it, to the center both ways |

**Try it.** Build the header above in your `summer-sound` page, with the `.site-header` rule from the align-items section and `.nav-links` as a flex row. Add the auto margin and watch the menu jump to the right. Then add `<a class="button" href="tickets.html">Get tickets</a>` after the `</nav>` and see that it travels with the menu.

## Try it in Flex Freight

[Flex Freight, puzzles 5 to 17](https://www.ask-codey.com/games/flex-freight/5): played right on the lesson page.

Thirteen puzzles to practice all of this on a loading dock: `justify-content` along the row, `align-items` and `align-self` across it, and an auto margin to push one crate away from the rest. Each group of puzzles starts with a guide where you can try every value first.

## Check yourself

3 questions to try on the lesson page.

## So what

The nav bar with its logo on the left, the welcome message in the middle of the screen and the button pushed to the bottom of a card are three of the most common layouts on the web. Each one is "make a flex container, then say where the space goes, along the main axis and across it".

## Key terms

- [Justify content](https://www.ask-codey.com/glossary/justify-content)
- [Align items](https://www.ask-codey.com/glossary/align-items)
- [Align self](https://www.ask-codey.com/glossary/align-self)
- [Auto margin](https://www.ask-codey.com/glossary/auto-margin)

## Cheat sheets

- [Flexbox Alignment: justify-content and align-items](https://www.ask-codey.com/cheat-sheets/css-flexbox-alignment-cheat-sheet)

## Related

- [Flexbox: Lining Things Up in a Row or a Column](https://www.ask-codey.com/lessons/css-flexbox-basics)
- [Flexbox Sizing: flex-grow, flex-shrink and flex-basis](https://www.ask-codey.com/lessons/css-flexbox-sizing)

Source: https://www.ask-codey.com/lessons/css-flexbox-alignment
