gitstack
open

Non-stretch children are measured at intrinsic width but laid out clamped, skipping wrap growth

#130
grindlemire · 2026-08-26T00:52:33Z view on GitHub

Follow-up to #126/#128, which fixed height measurement for the stretch default. The same class of gap remains for children that do not stretch on the cross axis.

In recomputeTextWrapping's column branch (internal/layout/flex.go), a non-stretch auto-width child is measured with HeightForWidth at its unclamped intrinsic width. The alignment phase later clamps the laid-out width to min(intrinsic, available). When the container is narrower than the child's intrinsic width, the child is measured at a width it never receives, so wrapping that the clamp forces goes unmeasured and the allocated height is too short.

Concrete repro shape: a table with intrinsic width 32 inside a flex-col items-start w-20 container is measured at width 32 (nothing wraps, short height) but laid out at width 20 (columns shrink, cells wrap taller). The cell rects overflow the table's rect and the sibling below overlaps the wrapped rows. The same applies to a wrapping text child with items-start or self-start.

The existing code comments scope the height propagation to "AlignStretch + Auto width, which is the default", so this is a known limitation rather than a regression. The fix shape mirrors #126: measure at the width the child will actually receive, which for non-stretch children is min(intrinsicW, availableCross) rather than the raw intrinsic width. Element.HeightForWidth's column branch has the same assumption (every child gets the full content width) and would need the same clamp for non-stretch children.