Menu

CSS flex-wrap and flex-direction: Rows, Columns, Wrapping

flex-wrap decides whether flex items squeeze onto one line or move to the next, and flex-direction decides whether they run in a row or a column. Learn both with live examples, the flex-flow shorthand, align-content, and a responsive card row with no media queries.

This page includes runnable editors - edit, run, and see output instantly.

flex-wrap: one line, or as many as needed

By default a flex container keeps all its items on one line (flex-wrap: nowrap) and shrinks them to fit. flex-wrap: wrap lets them keep their size and move onto the next line instead:

Each item asks for 100px, five of them in a 340px box. Five items and four 8px gaps need 532px, so without wrapping each item is squeezed to about 62px, because flex items shrink by default. With wrap they stay 100px: three fit on the first line and the other two move to a second line.

flex-wrap values

ValueWhat happens
nowrap (default)One line. Items shrink, and overflow the container once they cannot shrink further
wrapItems that do not fit start a new line below
wrap-reverseSame, but new lines stack upward: the first line is at the bottom

Watch items wrap

Drag the slider to change the container's width. The readout counts the lines and says how many items are on each:

At 400px, four 90px items and three 8px gaps (384px) fit on a line, so you get 4 + 2. Drag toward 620px and all six fit on one line; drag toward 120px and each item gets a line of its own.

flex-direction: row or column

flex-direction sets the direction items flow in, which is the main axis:

ValueItems runFirst item
row (default)side by side, in the writing directionat the start of the line
row-reverseside by side, reversedat the end of the line
columnstacked, top to bottomat the top
column-reversestacked, bottom to topat the bottom

In the two row boxes the items stretch to the full height of the box, because align-items: stretch works across the row. In the column boxes they stretch to the full width instead, for the same reason. The axes turned, and every alignment property turned with them (the justify-content page shows that in detail).

flex-flow: both in one line

flex-flow is the shorthand for flex-direction then flex-wrap:

.cards { flex-flow: row wrap; }      /* flex-direction: row; flex-wrap: wrap; */
.stack { flex-flow: column nowrap; } /* flex-direction: column; flex-wrap: nowrap; */

Responsive cards with wrap and no media query

Give each item a starting size with flex: 1 1 180px and let the row wrap. Each item grows to fill its line, and when a line cannot fit another 180px item, the next one wraps:

In a preview about 800px wide, three cards fit on the first line (about 253px each) and the last two share the second line, where each grows to about 386px. That is how flexbox works: every line shares out its own space, so cards on a short last line end up wider than the ones above. If you want the last card to stay the same width as the others, use grid with repeat(auto-fill, minmax(180px, 1fr)) instead (see the grid page).

align-content: spacing the lines

When a container wraps and is taller than its lines, align-content decides where the lines go. It takes the same values as justify-content, plus stretch:

In the first box both lines sit at the top. In the second the first line is at the top and the second at the bottom, with all the spare height between them.

Reversed order and accessibility

row-reverse, column-reverse and wrap-reverse only change where items are drawn. Screen readers and the Tab key still follow the HTML order, so a keyboard user moves through the items in the opposite direction to what they see. Reverse for visual effect only; when the order carries meaning, change it in the HTML.

Common mistakes

  • Items that shrink instead of wrapping. Items with flex: 1 start from a flex-basis of 0 and squeeze into one line. Give them a real basis, such as flex: 1 1 200px.
  • Putting flex-wrap on the items. It belongs on the flex container.
  • Using align-items to space wrapped lines. That aligns items within each line; the lines themselves move with align-content.
  • A lonely last item stretched across the whole row. That is flex-grow on a line with one item. Use grid if every card must be the same width.
  • Expecting flex-direction: column to fill a height. A column container is only as tall as its content unless you give it a height, so justify-content has no room to work.

Frequently Asked Questions

What does flex-wrap: wrap do?

It lets flex items move onto a new line when they do not fit in one row. With the default nowrap, the items stay on one line and shrink, or overflow the container if they cannot shrink any further.

Why is flex-wrap not working?

Wrapping only happens when the items' starting sizes add up to more than the container. Items with flex: 1 start from a flex-basis of 0, so they never wrap; give them a real starting size (flex: 1 1 200px or width: 200px). Also check that flex-wrap is on the flex container, not the items.

What is the difference between flex-direction row and column?

row (the default) places items side by side in the writing direction, and column stacks them top to bottom. The main axis turns with it, so in a column justify-content works vertically and align-items horizontally.

What is flex-flow?

A shorthand for flex-direction and flex-wrap in one declaration: flex-flow: row wrap; is the same as flex-direction: row; flex-wrap: wrap;.

What is the difference between align-items and align-content?

align-items places items inside their line. align-content places the lines themselves inside the container, so it only matters when the container has flex-wrap: wrap and is taller than its lines.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED