# Flexbox Wrapping and gap

flex-wrap lets flex items move onto a new line when they run out of room, gap puts even space between them, align-content places the lines, flex: 1 1 15rem makes a card row that fits any screen, and order changes what the eye sees but not what the keyboard follows.

Journeyman · CSS · Updated November 1, 2026

## After this lesson you can

- Wrap flex items onto new lines with flex-wrap, and space them with gap and align-content
- Build a card row that wraps, with cards that share each line, such as flex: 1 1 15rem
- Change an item's place with order, and explain why it can confuse keyboard users

## Key takeaways

- By default flex items stay on one line and squeeze. flex-wrap: wrap lets them move onto a new line when they run out of room, like words in a paragraph.
- gap sets the space between flex items, on every line and between the lines, and never adds space at the outside edges.
- A card row with flex-wrap: wrap and flex: 1 1 15rem on each card fits as many cards on a line as have room, and stretches them to fill it.
- align-content places the lines of a wrapping container when it's taller than they are. It does nothing when the items can't wrap.
- order moves an item on screen without moving it in the HTML. The keyboard and screen readers still follow the HTML, so use it with care.

Under each band's name, the *Summer Sound* festival site shows a few tags: *indie*, *folk*, *family friendly*, *late night*. Some bands have two tags and some have seven. Further down the page, the headliners sit in a row of cards: three across on a laptop, two on a tablet, one on a phone. Neither of those layouts knows in advance how much room it will get, and both are built the same way: flex items that move onto a new line when they run out of room. You'll use this for tag lists, photo strips, product grids and button groups, anywhere the number of things or the size of the screen can change.

The lesson uses words from the lessons before it: a **flex container** is the parent with `display: flex`, its children are **flex items**, the **main axis** is the direction they run in and the **cross axis** runs across it. `flex: 1 1 15rem` is the **flex shorthand** from *Flexbox Sizing: flex-grow, flex-shrink and flex-basis*: grow, shrink, and a starting size.

## When items don't fit: flex-wrap

When you type a paragraph, the words don't run off the edge of the page: when a line is full, the next word starts a new line. Flex items don't do that on their own. By default every item stays on **one line**, and when there isn't room, they squeeze: each one shrinks until its content can't get any smaller (its longest word), and then the rest spills out past the edge of the container.

Here are a band's tags as a flex row:

```html
<ul class="tags">
  <li>indie</li>
  <li>folk</li>
  <li>electronic</li>
  <li>hip-hop</li>
  <li>brass</li>
  <li>family friendly</li>
  <li>late night</li>
</ul>
```

On a 300-pixel phone column, all seven tags try to share one line: *family friendly* breaks onto two lines inside its own pill, and the last tags poke out past the right edge. The property that fixes it is **`flex-wrap`**:

```css
.tags {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
```

| `flex-wrap:` | What happens when the items don't fit |
|---|---|
| `nowrap` | they stay on one line and squeeze, then spill out (the default) |
| `wrap` | the next item starts a new line, below the last one |
| `wrap-reverse` | the next item starts a new line **above**: rarely what you want |

With `wrap`, each tag keeps its natural size, and the tags that don't fit on a line move down to the next one, so the list grows taller instead of wider. On the 300-pixel column, the seven tags take three lines.

You may also see **`flex-flow`**, a shorthand for `flex-direction` and `flex-wrap` together: `flex-flow: row wrap;` is the same as the two lines.

## Space between the items: gap

Tiles on a bathroom wall have the same thin line of grout between every pair, but none around the outside edge of the wall. **`gap`** is that grout for flex items:

```css
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
```

- `gap` puts the space **between** items, both between the items on a line and between the lines.
- It never adds space at the outside edges, so the first tag still starts flush with the left edge.
- Two values set the two directions separately: `gap: 1rem 0.5rem` is 1rem between the lines (the rows) and 0.5rem between items on a line (the columns). The long names are `row-gap` and `column-gap`.

Before `gap` worked in flexbox (every current browser has supported it since 2021), people spaced items with margins, and margins get in the way: a `margin-right` on every tag leaves an extra gap after the last tag on each line, so the lines never look centered. If you find `margin-right` on flex items in an older stylesheet, `gap` on the container is usually the cleaner fix. It also replaces the `margin-right` from the first flexbox lesson's nav links.

**Try it.** Make the tag list above in a `summer-sound` page, with a background color and some padding on each `li` so they look like pills. Narrow the window with `flex-wrap` off, then on, then add `gap`. Inspect the list: Chrome's and Edge's flex overlay shades the gaps.

![Before and after: seven genre tags squeezed into one line, with one tag split onto two lines and the last ones running past the edge, and the same tags with flex-wrap wrap and gap, sitting neatly on three lines with even space between them](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/08968cf83bab4532b2ba0ee712aaf911.webp)

## A card row that wraps

Now the headliners. Each card shows a band's name, its genre and the day it plays:

```html
<ul class="headliners">
  <li class="card">
    <h3>Neon Tide</h3>
    <p>Synth-pop</p>
    <p class="set-time">Friday, 9:30 PM</p>
  </li>
  <!-- five more cards like this one -->
</ul>
```

Three lines of CSS turn the list into a row that fits any screen:

```css
.headliners {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.card {
  flex: 1 1 15rem;
}
```

Read `flex: 1 1 15rem` as a sentence: "start at 15rem wide, may grow, may shrink". With the usual root font size, 15rem is 240 pixels. The browser fits as many 240-pixel cards on a line as there's room for, wraps the rest, and then the `1` for grow shares each line's leftover space, so the cards on a line stretch to fill it:

| Row width (gap 24px) | Cards per line | Each card |
|---|---|---|
| 1000px | 3 (four would need 4 × 240 + 3 × 24 = 1032) | about 317px |
| 600px | 2 | 288px |
| 360px (a phone) | 1 | 360px: grown to fill the line |

No media query, no counting cards: the layout works it out for each screen. Change `15rem` to make the cards wider or narrower before they wrap.

One thing to know: each line shares its own space. Six cards on a 1000-pixel row make two full lines of three, but with **five** cards, the second line has only two, and they each grow to 488 pixels, wider than the cards above them. Sometimes that looks fine; when every card must stay the same width, CSS Grid is the better tool, and *CSS Grid: Rows and Columns* shows it.

![The headliner cards on three screens: three cards across on a laptop, two across on a tablet and one per line on a phone, with the same 24-pixel gap between them every time](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/6e63a47273b546549a42d9bdaaa1174e.webp)

## Placing the lines: align-content

When a wrapping container is **taller** than its lines (a panel with a fixed height, say), there's leftover space on the cross axis, between and around the lines. **`align-content`** decides where it goes:

```css
.photo-wall {
  display: flex;
  flex-wrap: wrap;
  height: 600px;
  align-content: flex-start;
}
```

It takes the values you know from `justify-content` (`flex-start`, `center`, `flex-end`, `space-between`, `space-around`, `space-evenly`) plus `stretch`. The default behaves like `stretch`: the lines share out the extra height, which is why a tall wrapping container sometimes shows big strange gaps between its lines. `align-content: flex-start` packs the lines at the top instead.

Two differences from its neighbors are worth keeping straight:

- **`align-items`** lines up the items **inside each line**. **`align-content`** moves **the lines themselves**.
- **`align-content` only works on a container that can wrap.** With the default `flex-wrap: nowrap` there's one line and nothing for it to place, so the browser ignores it.

## Changing the order: order

Every flex item has an **`order`**, a number that's 0 unless you change it. The browser shows the items from the lowest number to the highest, and items with the same number keep their HTML order. A negative number moves an item to the front:

```css
.card.featured {
  order: -1;
}
```

The festival's HTML lists Neon Tide, The Midnight Pancakes and Juniper Road, in that order. If Juniper Road's card has the class `featured`, it now **shows** first.

But only to the eye. A screen reader still reads the cards in the HTML's order, and someone using the **Tab** key to move between the links on the page goes through them in the HTML's order too: Neon Tide's link, then The Midnight Pancakes', then back to the front of the row for Juniper Road's. The highlight that shows where they are jumps around the screen, and what's read aloud doesn't match what's shown. Accessibility guidelines (WCAG, the *Web Content Accessibility Guidelines*) call this keeping a *meaningful sequence* and a sensible *focus order*. The same goes for `row-reverse` and `column-reverse`.

So:

- **When the order matters, change the HTML.** Move Juniper Road's card to the top of the list, and the screen, the keyboard and the screen reader all agree.
- **Use `order` only for a change that doesn't affect meaning or interaction**, such as moving a decorative picture below the text on a small screen.

A newer property, `reading-flow`, lets the keyboard follow the visual order of a flex container. As of October 2026 it works in Chrome and Edge but not yet in Firefox or Safari, so it isn't something to rely on yet.

**Try it.** Give one of your cards a link and `order: -1`, then click the address bar and press **Tab** repeatedly. Watch where the focus highlight goes, and in what order.

## Try it in Flex Freight

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

Too many crates for one row? These puzzles practice `flex-wrap`, `gap`, `align-content` and `order` on the loading dock, until every crate sits on its spot.

## Check yourself

3 questions to try on the lesson page.

## So what

Wrapping is what makes a row of tags or cards fit a phone and a wide screen with the same CSS, and `gap` keeps it tidy. Keep the HTML in the order people should read it, and let the CSS decide how much fits on a line.

## Key terms

- [Flex wrap](https://www.ask-codey.com/glossary/flex-wrap)
- [Gap](https://www.ask-codey.com/glossary/gap)
- [Align content](https://www.ask-codey.com/glossary/align-content)
- [Order](https://www.ask-codey.com/glossary/order)

## Cheat sheets

- [Flexbox Wrapping and gap](https://www.ask-codey.com/cheat-sheets/css-flexbox-wrapping-cheat-sheet)

## Related

- [Flexbox Sizing: flex-grow, flex-shrink and flex-basis](https://www.ask-codey.com/lessons/css-flexbox-sizing)
- [Flexbox Alignment: justify-content and align-items](https://www.ask-codey.com/lessons/css-flexbox-alignment)
- [CSS Grid: Rows and Columns](https://www.ask-codey.com/lessons/css-grid-basics)

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