Bare text in a flex container becomes an anonymous flex item, one per contiguous run of text
Fact
Flex layout does not lay out inline content; it lays out flex items. Any non-empty run of text directly inside a flex container is wrapped in an anonymous flex item of its own, as a sibling of the element boxes around it.
So this markup, in a flex-direction: column container, renders on two lines rather than one:
<label>Focus <span class="unit">min</span></label>
Focus becomes one anonymous item and the <span> another, and the column direction puts each on its own row. The <span> being display: inline changes nothing — that property describes how a box participates in inline layout, and inside a flex container it is blockified and never gets the chance.
The unit is the contiguous run, not the text node: el.append('🌾', 'Plainsfolk') makes two adjacent text nodes but one item, so gap never separates them.
Why it matters
The markup looks like ordinary inline content, so the split reads as a wrapping or width bug and invites white-space: nowrap or a width bump, neither of which helps. In a row container it is easier to miss entirely: the text and the span sit side by side as intended, but they are now two items, so gap, justify-content, flex: 1 and :first-child all count one more item than the markup suggests.
How to apply
- Wrap the text in an element so the pair is one item:
<span class="lbl">Focus <span class="unit">min</span></span>. - Conversely, an icon and its label need two elements, not two strings, for
gapto apply. - Treat "every child of a flex or grid container is an item, including bare text" as the rule when counting items for
gapornth-child. - The same anonymous-item rule applies to grid containers.
- Whitespace-only text between elements is not wrapped, so formatting newlines add no items.