Topic 7.4
Wrapping and Gaps
In one line
flex-wrap: wrap lets items break onto new lines instead of shrinking, gap puts fixed space between items and lines without touching the outer edges, and order changes only the visual position of an item, never its reading or Tab order.
Think of it like this
Writing on lined paper. When a word doesn't fit at the end of a line, you don't squash it: you start a new line. That's flex-wrap: wrap. The space you leave between words and between lines is the gap. And if you number your sentences "read this one first", the paper still has them in the order you wrote them; only a reader who follows the numbers sees a different order. That's order.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- `flex-wrap`
- Whether items may break onto new lines:
nowrap(default),wraporwrap-reverse. - Flex line
- One row (or column) of items in a flex container. Wrapping creates several lines.
- Multi-line container
- A flex container with
flex-wrap: wraporwrap-reverse, even if it currently has one line. - `flex-flow`
- A shorthand for
flex-directionandflex-wraptogether, likeflex-flow: column wrap. - `gap`
- Space between items and between lines. Shorthand for
row-gapandcolumn-gap. - `row-gap` / `column-gap`
- The space between lines, and the space between items in a line (for a row container).
- `order`
- An integer that changes an item's visual position. Lower numbers come first. Default
0. - Visual order vs DOM order
- What the eye sees, versus the order in the HTML, which keyboards and screen readers follow.
Step by step
01See what nowrap does
Five 60px items in a 200px row need 300px. With the default nowrap they stay on one line and shrink to 40px each. Add a long word and they would overflow instead.
.row {
display: flex;
width: 200px; /* 5 x 60 = 300px of items */
}
.row > * { flex-basis: 60px; }02Let the items wrap
With flex-wrap: wrap, three items fit on the first line (180px) and the fourth starts line 2. The items keep their 60px; the 20px left on each line is free space for justify-content.
.row {
display: flex;
flex-wrap: wrap;
width: 200px;
}03Add gaps
gap: 10px adds 10px between items in a line and 10px between lines. Three items plus two gaps is 60 + 10 + 60 + 10 + 60 = 200px: still a perfect fit. Nothing is added at the edges.
.row {
display: flex;
flex-wrap: wrap;
gap: 10px; /* or: row-gap: 10px; column-gap: 10px; */
}04Build a responsive row without media queries
Give items a basis and let them grow: flex: 1 1 150px. On a wide screen four fit per line; on a phone one. They grow to fill each line.
.cards { display: flex; flex-wrap: wrap; gap: 16px; }
.cards > * { flex: 1 1 150px; }05Reorder with care
order: -1 moves an item to the start of the line, visually. A keyboard user pressing Tab still visits the items in HTML order, so use it for decoration, not for things people read or press in sequence.
.featured { order: -1; } /* shown first, still read where it is in the HTML */Try it yourself
- 1
Predict the wrap point
In the first example, change the item basis to
70px. Predict how many items fit on the first line of thewraprow, and the nowrap widths. (Two per line: 140px fits, 210px doesn't. In the nowrap row, 350px must fit into 200px, so each item loses 30px and ends at 40px again.) - 2
Break the perfect fit
In the gap example, change
.sametogap: 12px. Predict where item 3 goes. (60 + 12 + 60 + 12 + 60 = 204px is more than 200, so item 3 wraps to line 2.) - 3
Center the last line
In the card example, change the cards to
flex: 0 1 110pxand addjustify-content: centerto.cards. Predict what happens to the last line. (The cards stop growing, keep 110px plus padding, and the last line is centred.)
Code & diagrams
`nowrap` squeezes all five onto one line (300px into 200px, so each loses 20px). `wrap` keeps 60px and moves items 4 and 5 to a second line. `wrap-reverse` puts the first line at the bottom.
Preview
Console
Nothing logged yet.Expected console output
nowrap: widths 40,40,40,40,40 | tops 0,0,0,0,0
wrap: widths 60,60,60,60,60 | tops 0,0,0,30,30
wrap-reverse: widths 60,60,60,60,60 | tops 30,30,30,0,0With `gap: 10px`, three items and two gaps fill exactly 200px, and line 2 starts at 30 + 10 = 40. With `gap: 20px 5px`, the first value is the row gap (between lines) and the second the column gap (between items).
Preview
Console
Nothing logged yet.Expected console output
same: x 0,70,140 | item 4 top 40 | row-gap 10px
split: x 0,65,130 | item 4 top 50 | row-gap 20pxC (`order: -1`) jumps to the front, B (`order: 2`) to the back; A and D share `order: 0` and keep their HTML order. Click A and press Tab a few times: focus goes A, B, C, D, jumping around the screen.
Preview
Console
Nothing logged yet.Expected console output
HTML and Tab order: A B C D
Visual order: C A D B
order values: 0, 2, -1, 0Make the preview wider and narrower: the number of cards per line changes on its own. The last line's cards grow to fill their line, so they can be wider than the others. Grid's `auto-fill` (Topic 8.2) keeps every column the same.
Preview
Console
Nothing logged yet.Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget to turn on wrapping
In the card example, remove flex-wrap: wrap and make the preview narrow.
Break #2
Use margins instead of gap
Replace gap: 10px in the .same row with .same b { margin-right: 10px; }.
Myth vs fact
Myth
gap only works in Grid.
Fact
gap, row-gap and column-gap have worked in Flexbox in every major browser since 2021 (Safari 14.1 was the last).
Myth
Wrapped flex items line up in columns.
Fact
Every flex line is sized on its own, so items on different lines only line up by accident. For aligned columns, use Grid.
Myth
order is a good way to fix the order of a page.
Fact
It changes only what you see. Keyboard and screen-reader users still get the HTML order, so meaningful order must be fixed in the HTML.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Feature detection for flex
gapwas impossible with@supports (gap: 1px), becausegapalready existed for Grid; that's why the negative-margin hack lived on long after Grid shipped. Today you can usegapin Flexbox without a fallback. - ▸
Percentage
gapvalues in Flexbox resolve against the container's content box; in an auto-height column container a percentage row gap can't resolve and is treated as 0. - ▸
orderalso affects painting order (items with a laterorderpaint on top when they overlap) and is howz-indexstacking ties are broken inside flex containers. Note that flex items can usez-indexwithoutposition, and it creates a stacking context (Phase 6, Topic 6.4). - ▸
flex-wrap: wrapwithflex-direction: columnneeds a definite height to wrap into, and browsers historically mis-sized the container's width in that case (it doesn't grow to fit extra columns). Grid withgrid-auto-flow: columnis more reliable for column-wise flow.
Remember this
- 1
By default,
flex-wrapisnowrap: every item stays on one line, and if they don't fit they shrink (Topic 7.3). If they can't shrink any further, they overflow the container.flex-wrap: wrapallows a multi-line flex container: when the next item doesn't fit, it moves to a new flex line. Each line is laid out on its own: growing, shrinking andjustify-contenthappen per line, so items on different lines don't line up with each other. - 2
flex-wrap: wrap-reversewraps too, but stacks the lines in the opposite direction on the cross axis: the first line sits at the bottom (in a row). The shorthand **flex-flow** setsflex-directionandflex-wraptogether:flex-flow: row wrap. - 3
**
gapsets space between** items and between lines, never at the outer edges.gap: 16pxsets both;gap: 8px 16pxsetsrow-gap(between lines) first andcolumn-gap(between items in a line) second. Beforegapworked in Flexbox (all major browsers since 2021), people used margins on every item and a negative margin on the container to cancel the edges.gapis simpler: the space is counted when items are sized, soflex: 1items still fill the line exactly. - 4
Wrapping decides line breaks from each item's hypothetical size (its basis, clamped by min and max).
flex: 1 1 150pxwithflex-wrap: wrapis a classic responsive trick: items are at least about 150px, as many fit per line as possible, and then they grow to fill the line. No media query needed. The catch: the last line grows too, so a lone last item can become very wide. When you need every column to line up, use Grid (Topic 8.2,auto-fill). - 5
**
order** is an integer on an item (default0). Items are laid out in ascendingorder, and items with the same value keep their HTML order. Negative values move an item before all the0items.orderchanges only the visual order. Screen readers read the HTML order and the Tab key moves focus in HTML order, soordermust never change the meaning of the content. Use it for small visual swaps, for example putting an image first on narrow screens.
Explain it without notes
What is the difference between flex-wrap: nowrap and wrap when items don't fit?
Why is gap better than margins for spacing flex items?
What does order change, and what doesn't it change?
How can you make a responsive row of cards with Flexbox and no media queries, and what is its weakness?
Practice
Make a list of tags (<span class="tag">) wrap onto new lines with 8px between tags and 6px between lines.
Write CSS for a row of items that wraps, with 16px gaps, where each item is at least 200px and grows to fill the line.
A product card has <img> then <h2> in the HTML. Show the heading above the image visually. Is order a good idea here?
Trade-offs
- ↔
Flex wrapping adapts to content and needs no breakpoints, but you give up aligned columns. Grid adds alignment across lines at the cost of deciding track sizes.
- ↔
ordersaves duplicating HTML for different layouts, but every use creates a mismatch between what is seen and what is read, so keep it for decoration.
Done when you can
I can make items wrap and explain what
nowrapdoes instead.I can use
gap,row-gapandcolumn-gap, and knowgap: a bis row then column.I can predict where items wrap when gaps are included.
I can build a responsive wrapping row with
flex: 1 1 <size>.I can use
orderand explain why it doesn't change Tab order.