Skip to content

Commit 9dbff05

Browse files
Dagurfacebook-github-bot
authored andcommitted
Layout breaks when the first element has a different minWidth than the rest
Summary: fixes react/yoga#2006 `distributeFreeSpaceFirstPass` decrements `totalFlexGrowFactors` / `totalFlexShrinkScaledFactors` as it freezes items, but only reduces `remainingFreeSpace` after the loop. Items after the first frozen one get an inflated fair share and freeze spuriously. When the first item clamps, the whole line freezes and `remainingFreeSpace` drains to 0, so the second pass has nothing to distribute and everything falls back to its flex basis — a 540px row of three `flexGrow: 1` items with `maxWidth: 180` and minWidths 60/30/30 lays out as 60/30/30 instead of 180/180/180. Snapshot both totals before the loop and divide by the snapshot. The first pass is then iteration 1 of CSS Flexbox §9.7, and independent of child order. Changelog: [General][Fixed] - Fix a flex line collapsing to its minimum sizes when the first item clamps to its min or max main size X-link: react/yoga#2021 Reviewed By: javache Differential Revision: D119142409 Pulled By: pasqualeanatriello
1 parent 25b6fd5 commit 9dbff05

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,19 @@ static void distributeFreeSpaceFirstPass(
12801280
float boundMainSize = 0;
12811281
float deltaFreeSpace = 0;
12821282

1283+
// The first pass performs a single distribution of the free space over all
1284+
// of the line's flexible items, so every item's tentative size must be
1285+
// computed against the *original* totals. The totals are still reduced as
1286+
// items get frozen below (so the second pass can redistribute), but those
1287+
// reduced values must not feed back into the fair-share calculation for the
1288+
// remaining items: doing so inflates their tentative size and can freeze
1289+
// items that should still be able to grow/shrink (see
1290+
// https://github.com/react/yoga/issues/2006).
1291+
const float originalTotalFlexGrowFactors =
1292+
flexLine.layout.totalFlexGrowFactors;
1293+
const float originalTotalFlexShrinkScaledFactors =
1294+
flexLine.layout.totalFlexShrinkScaledFactors;
1295+
12831296
for (auto currentLineChild : flexLine.itemsInFlow) {
12841297
float childFlexBasis = boundAxisWithinMinAndMax(
12851298
currentLineChild,
@@ -1299,8 +1312,7 @@ static void distributeFreeSpaceFirstPass(
12991312
flexShrinkScaledFactor != 0) {
13001313
baseMainSize = childFlexBasis +
13011314
flexLine.layout.remainingFreeSpace /
1302-
flexLine.layout.totalFlexShrinkScaledFactors *
1303-
flexShrinkScaledFactor;
1315+
originalTotalFlexShrinkScaledFactors * flexShrinkScaledFactor;
13041316
boundMainSize = boundAxisWithAutoMin(
13051317
currentLineChild,
13061318
mainAxis,
@@ -1328,8 +1340,8 @@ static void distributeFreeSpaceFirstPass(
13281340
// Is this child able to grow?
13291341
if (yoga::isDefined(flexGrowFactor) && flexGrowFactor != 0) {
13301342
baseMainSize = childFlexBasis +
1331-
flexLine.layout.remainingFreeSpace /
1332-
flexLine.layout.totalFlexGrowFactors * flexGrowFactor;
1343+
flexLine.layout.remainingFreeSpace / originalTotalFlexGrowFactors *
1344+
flexGrowFactor;
13331345
boundMainSize = boundAxis(
13341346
currentLineChild,
13351347
mainAxis,

0 commit comments

Comments
 (0)