What changes when you write display: flex?
Setting display: flex on an element makes it a flex container and every direct child a flex item. Grandchildren are unaffected; they keep their normal layout inside their own parent. The container still behaves as a block on the outside, taking the full width of its parent, while its children are now laid out in a row.
Flex items behave differently from blocks. They sit side by side, they size to their content by default, their margins no longer collapse, and they all stretch to the height of the tallest item in the row. Text nodes that sit directly in the container become anonymous flex items too, which is why loose text next to a span can line up in odd ways.
Use display: inline-flex when the container itself should flow inside a line of text, for example a small icon and label pair inside a sentence.
.tags {
display: flex;
}

flex-direction to column and the two axes swap.What are the main axis and the cross axis?
Every flex container has two axes. The main axis is the direction items are placed in; the cross axis runs at right angles to it. The alignment properties in the next lesson are all defined against these axes, never against left, right, top or bottom, so learning the axes first saves a lot of guessing.
With the default flex-direction: row, the main axis runs in the writing direction, left to right in English and right to left in Arabic or Hebrew. With flex-direction: column, the main axis runs top to bottom. The row-reverse and column-reverse values flip the start and end of the main axis.
Turn on the Layout lens in the preview, or click the flex badge next to the container in DevTools, and the browser draws the container, the items and the gaps for you.
.steps {
display: flex;
flex-direction: column;
}How do wrapping and gap work?
By default a flex container keeps every item on one line. When the items do not fit, they shrink, and if they cannot shrink any further they overflow the container. Add flex-wrap: wrap and items that do not fit move onto a new line instead. Each line is laid out separately, so items on the last line do not line up with the columns above them. If you need columns that line up, that is a job for grid.
The gap property puts space between items and between wrapped lines, and never on the outer edges. It replaces the old trick of a margin on every item and a negative margin on the container. Gap in flex layouts is supported in all current browsers. You can set the two directions separately with row-gap and column-gap, or with two values on gap.
.tags {
display: flex;
flex-wrap: wrap;
gap: 8px 12px;
}How do flex-grow, flex-shrink and flex-basis share space?
Flexbox sizes items in two steps. First each item gets its flex-basis, its starting size along the main axis. The default auto means use the item's width (or height in a column), or its content size if no width is set. Then the browser compares the total of those sizes with the container.
If space is left over, it is shared among items in proportion to their flex-grow. An item with flex-grow: 2 gets twice as much of the leftover space as one with 1. The default is 0, so items do not grow unless asked. If the items are too big, they shrink in proportion to flex-shrink multiplied by their basis. The default is 1, so every item shrinks a little.
That proportional sharing is why two items with flex-grow: 1 and different content can end up different widths: they share the leftover space equally, on top of different starting sizes.
What do flex: 1, flex: none and flex: 0 0 200px mean?
The flex shorthand sets grow, shrink and basis in that order, and it is the form you will see most. A few values cover nearly every case.
Prefer the shorthand to setting the three longhands one by one; it resets the basis to a sensible value. Be careful with flex: 1 when the content is long: the basis of 0 combined with an automatic minimum width can still let a long word or a wide image push the item wider. The fix, min-width: 0, is covered in the flex alignment lesson.
.search {
flex: 1;
}
.go {
flex: none;
}flex: 1means1 1 0%: grow, shrink, and start from zero, so items withflex: 1end up equal widths regardless of content.flex: automeans1 1 auto: grow and shrink, starting from the content size.flex: nonemeans0 0 auto: keep the content orwidthsize and never grow or shrink. Good for icons, buttons and avatars.flex: 0 0 200pxfixes the item at 200px along the main axis, like a sidebar that should not move.- The default, with no
flexset, is0 1 auto: stay at content size and shrink only when space runs out.
Is it safe to reorder items with order?
The order property changes the visual position of a flex item. Items are sorted by their order value, lowest first, and items with the same value keep source order. The default is 0, so order: -1 moves one item to the front.
The danger is that only the drawing changes. Tab focus, screen readers and text selection still follow the HTML. A keyboard user tabbing through a toolbar sees focus jump back and forth across the screen, which breaches the WCAG requirement that focus order preserves meaning. The row-reverse and column-reverse directions have the same problem.
Use order for decorative tweaks, such as moving an image above a caption on narrow screens when neither is interactive. If the order matters for meaning or contains links and buttons, change the HTML instead. A reading-flow property to fix this is being added to browsers, but it is not available everywhere yet.
When should you choose flexbox over grid?
Flexbox is one-dimensional. It lays items along one axis and lets their content decide their size. That suits navigation bars, toolbars, tag lists, a button with an icon, a media object with an avatar and text, and any row where items should be as wide as they need to be.
Grid is two-dimensional. You define columns and rows first, and items drop into them. Choose it when things need to line up in both directions: card galleries, page layouts, forms with labels in one column and inputs in the next. A quick test: if you find yourself setting fixed widths on flex items to make wrapped rows line up, you want grid.
The two mix freely. A page built with grid often has flex containers inside each card, and a grid can be a flex item.
What should you check in AI-written flexbox?
Generated code often puts display: flex on the wrong element, such as on the items instead of their parent, or on a grandparent whose children are not the boxes that need to line up. Check that the container is the direct parent of the items.
Watch for flex: 1 on every item, including buttons and icons that should stay small, and for width set on items that also have a flex-basis, where the basis wins. Look for spacing done with margins on every item next to a gap, which doubles the space. Finally, search for order and row-reverse, and check they are not shuffling links or form fields away from source order.
Field notes
display: flexturns the direct children into flex items; grandchildren keep their normal layout.- Items flow along the main axis, and the cross axis runs at right angles to it.
- Use
gapfor space between items andflex-wrapto let them move onto new lines. - The
flexshorthand sets grow, shrink and basis, in that order.
Easy to get wrong
Flex goes on the parent. Setting it on the items only changes how their own content is laid out.
Margins leave extra space after the last item. Gap only goes between items and between wrapped lines.
Flex items shrink by default, so a fixed-width icon can be squashed in a tight row. flex: none keeps it at size.
Reversing the direction reverses the visual order of links but not the tab order. Align them to the end instead.
Questions people ask
Does display: flex affect grandchildren?
No. Only direct children become flex items. Nested elements keep their own layout unless their parent is also a flex container.
Why are my flex items all the same height?
Items stretch along the cross axis by default. Set align-items on the container or align-self on an item to change it.
Is flex: 1 the same as flex-grow: 1?
No. flex: 1 also sets the basis to 0, so items start from zero and end up equal. flex-grow: 1 alone keeps a basis of auto, so content size still counts.
Do floats work inside a flex container?
No. float is ignored on flex items, so you can drop old float rules when switching to flex.