Bug Description
When a WDiv flex-row uses justify-between alongside children that have flex-1, the space distribution doesn't work correctly — non-flex children are not pushed to the right edge. Instead, they sit immediately adjacent to the flex-1 child.
Observed behavior: First render may show correct positioning, then children shift left on rebuild.
Expected behavior: flex-1 child fills remaining space (via Expanded), non-flex children stay at the right edge — matching CSS justify-content: space-between with flex: 1 behavior.
Reproduction
WDiv(
className: 'w-full flex flex-row items-center justify-between gap-4',
children: [
// Title section — should fill remaining space
WDiv(
className: 'flex-1 min-w-0',
child: WText('Long title that should truncate...', className: 'truncate'),
),
// Actions — should be pushed to the right edge
WDiv(
className: 'shrink-0',
child: WText('Action'),
),
],
)
Workaround: Replace WDiv Row with native Flutter Row + Expanded:
Row(children: [Expanded(child: titleWidget), actionWidget])
Root Cause
In w_div.dart lines 404-421, when needsSpaceDistribution is true (i.e. justify-between, space-around, or space-evenly), all children are wrapped with Flexible:
final needsFlexible = needsSpaceDistribution || hasOverflowClip;
final rowChildren = needsFlexible
? gappedChildren.map((child) {
if (child is SizedBox || child is Flexible || child is Expanded) {
return child;
}
if (child is WDiv && _hasFlexClass(child.className)) {
return child;
}
// ...
return Flexible(child: child); // ← wraps ALL non-flex children
}).toList()
: gappedChildren;
Why this breaks
- The
flex-1 child correctly becomes Expanded(flex: 1) — tight fit, takes all remaining space.
- Non-flex children (e.g.
shrink-0 actions) get wrapped with Flexible(child: ...) — loose fit, flex: 1 by default.
- Now the Row has two flex children — one
Expanded(flex: 1) and one Flexible(flex: 1). Flutter distributes space equally between them by flex ratio, making both compete for the same space.
justify-between becomes irrelevant because there's no non-flex space left to distribute — all children are flex participants.
Additional issue: shrink-0 semantics
In flexbox_grid_parser.dart line 112:
'shrink-0': FlexFit.tight, // flex-shrink: 0 (don't shrink)
shrink-0 maps to FlexFit.tight, but CSS flex-shrink: 0 means "don't shrink below intrinsic size" — it should prevent the child from being wrapped in Flexible at all, not set it to tight fit. A tight Flexible forces the child to fill its flex allocation, which is the opposite of "keep intrinsic size."
Suggested Fix
When needsSpaceDistribution is true, don't blindly wrap all children with Flexible. Instead:
- Skip wrapping children that have
shrink-0 (they should keep their intrinsic size)
- Only wrap children that explicitly opt into shrinking
- Respect that
flex-1 children already handle their own Expanded wrapping
final rowChildren = needsFlexible
? gappedChildren.map((child) {
if (child is SizedBox || child is Flexible || child is Expanded) {
return child;
}
// Skip flex-N children (they self-wrap with Expanded)
if (child is WDiv && _hasFlexClass(child.className)) {
return child;
}
// Skip shrink-0 children (should not shrink)
if (child is WDiv && _hasShrinkZero(child.className)) {
return child;
}
return Flexible(child: child);
}).toList()
: gappedChildren;
Environment
- Wind UI:
^1.0.0-alpha.4
- Flutter: 3.41.6
- Dart SDK: ^3.11.3
Bug Description
When a
WDivflex-row usesjustify-betweenalongside children that haveflex-1, the space distribution doesn't work correctly — non-flex children are not pushed to the right edge. Instead, they sit immediately adjacent to theflex-1child.Observed behavior: First render may show correct positioning, then children shift left on rebuild.
Expected behavior:
flex-1child fills remaining space (viaExpanded), non-flex children stay at the right edge — matching CSSjustify-content: space-betweenwithflex: 1behavior.Reproduction
Workaround: Replace WDiv Row with native Flutter
Row+Expanded:Root Cause
In
w_div.dartlines 404-421, whenneedsSpaceDistributionis true (i.e.justify-between,space-around, orspace-evenly), all children are wrapped withFlexible:Why this breaks
flex-1child correctly becomesExpanded(flex: 1)— tight fit, takes all remaining space.shrink-0actions) get wrapped withFlexible(child: ...)— loose fit,flex: 1by default.Expanded(flex: 1)and oneFlexible(flex: 1). Flutter distributes space equally between them by flex ratio, making both compete for the same space.justify-betweenbecomes irrelevant because there's no non-flex space left to distribute — all children are flex participants.Additional issue:
shrink-0semanticsIn
flexbox_grid_parser.dartline 112:shrink-0maps toFlexFit.tight, but CSSflex-shrink: 0means "don't shrink below intrinsic size" — it should prevent the child from being wrapped inFlexibleat all, not set it to tight fit. A tightFlexibleforces the child to fill its flex allocation, which is the opposite of "keep intrinsic size."Suggested Fix
When
needsSpaceDistributionis true, don't blindly wrap all children withFlexible. Instead:shrink-0(they should keep their intrinsic size)flex-1children already handle their ownExpandedwrappingEnvironment
^1.0.0-alpha.4