Flexbox Layout
The flex formatting context implements CSS Flexbox Level 1 (§9) at a high level of fidelity. display: flex (or inline-flex) dispatches into layout_flex_children().
Direction and Wrapping
.container {
display: flex;
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
}
Multi-line wrapping produces a list of flex lines. Each line is sized independently; align-content distributes leftover cross-axis space among lines.
Alignment
Main axis — justify-content
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
- space-between: first item at start, last at end, equal gaps between
- space-around: half-gap at edges, full gaps between items
- space-evenly: equal spacing everywhere, including edges
Cross axis — align-items, align-self
align-items: stretch | flex-start | flex-end | center | baseline;
align-self on individual items overrides the container's align-items.
Multi-line — align-content
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
Active only in multi-line flex containers (i.e. flex-wrap: wrap).
Flex Factors (grow / shrink / basis)
.item {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 200px;
}
The flex shorthand is expanded by the parser into the three longhands. The layout algorithm implements the canonical iterative freeze loop (CSS-Flex-1 §9.7):
- Compute initial flex base sizes from
flex-basisor auto content size. - Distribute remaining free space proportionally to
flex-growvalues. - If overflow: shrink items proportionally to
flex-shrink × flex-base-size. - Clamp each item to its
min-width/max-width— frozen items stop participating. - Repeat steps 2-4 until no items change (typically 1-2 iterations).
Gap
gap: 10px 20px; /* row-gap column-gap */
row-gap: 10px;
column-gap: 20px;
order
.item-first { order: -1; }
.item-last { order: 1; }
Items are stable-sorted by order then source index. Layout reorders coordinates but the children vector stays in source order — hit-testing ignores visual order, matching CSS behavior.
Auto Margins on Flex Items
margin: auto on a flex item absorbs free space on the main axis. If two items both have margin-left: auto, they split the remaining space (centering their adjacent outer edges). On the cross axis, a single margin: auto on the perpendicular edge pushes the item against the opposite side — e.g. margin-top: auto aligns to the bottom.
Content-Based Minimum Size
Per CSS-Flex-1 §4.5, min-width: auto on a flex item resolves to its content-based minimum size rather than zero. This prevents items from shrinking below their natural content width. The layout engine computes this by measuring the item at its flex-basis and clamping shrinkage.
Complete Example
.card-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
gap: 16px;
padding: 20px;
}
.card {
flex: 1 1 250px;
max-width: 350px;
padding: 24px;
border: 2px solid #e0e0e0;
border-radius: 12px;
}
.card.featured {
flex-grow: 2;
order: -1;
}
This produces a wrapped row of cards. The featured card appears first (order -1), takes twice the share (flex-grow: 2), and all cards wrap when the container narrows below 250px × count.