Unexpected Yoga calculation results when using min/max sizes for top/bottom or left/right nodes
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18.9k
- Forks
- 1.6k
- Avg merge
- 1m
- Merged PRs (30d)
- 1
Description
Report
- I have searched existing issues and this is not a duplicate
Issues and Steps to Reproduce
I've tried to create three rows and three columns on second row.
All rows should be stretched to root node size.
All columns (in second row) should stretch to row size.
Left and right columns should have different min/max width.
Top and bottom row should have different min/max height.
Expected Behavior
There should not be empty space between stretched nodes.
Actual Behavior
There is empty space between stretched nodes.

Link to Code
I am using java bindings and here is code:
private Vector2f minTop = new Vector2f(200, 20);
private Vector2f minBottom = new Vector2f(200, 20);
private Vector2f minLeft = new Vector2f(100, 20);
private Vector2f minRight = new Vector2f(120, 20);
private Vector2f minCenter = new Vector2f(50, 50);
private Vector2f maxTop = new Vector2f(Float.MAX_VALUE, 120);
private Vector2f maxBottom = new Vector2f(Float.MAX_VALUE, 80);
private Vector2f maxLeft = new Vector2f(300, Float.MAX_VALUE);
private Vector2f maxRight = new Vector2f(200, Float.MAX_VALUE);
private Vector2f maxCenter = new Vector2f(Float.MAX_VALUE, Float.MAX_VALUE);
private Vector4f midRow = new Vector4f();
private Vector4f top = new Vector4f();
private Vector4f bottom = new Vector4f();
private Vector4f left = new Vector4f();
private Vector4f center = new Vector4f();
private Vector4f right = new Vector4f();
private Vector2f size = new Vector2f();
protected void update() {
long rootNode = Yoga.YGNodeNew();
long mNode = Yoga.YGNodeNew();
long tNode = Yoga.YGNodeNew();
long lNode = Yoga.YGNodeNew();
long cNode = Yoga.YGNodeNew();
long rNode = Yoga.YGNodeNew();
long bNode = Yoga.YGNodeNew();
Yoga.YGNodeInsertChild(rootNode, tNode, 0);
Yoga.YGNodeInsertChild(rootNode, mNode, 1);
Yoga.YGNodeInsertChild(rootNode, bNode, 2);
Yoga.YGNodeInsertChild(mNode, lNode, 0);
Yoga.YGNodeInsertChild(mNode, cNode, 1);
Yoga.YGNodeInsertChild(mNode, rNode, 2);
Yoga.YGNodeStyleSetFlexDirection(rootNode, Yoga.YGFlexDirectionColumn);
Yoga.YGNodeStyleSetAlignItems(rootNode, Yoga.YGAlignStretch);
Yoga.YGNodeStyleSetJustifyContent(rootNode, Yoga.YGJustifySpaceBetween);
Yoga.YGNodeStyleSetFlexDirection(mNode, Yoga.YGFlexDirectionRow);
Yoga.YGNodeStyleSetAlignItems(mNode, Yoga.YGAlignStretch);
Yoga.YGNodeStyleSetJustifyContent(mNode, Yoga.YGJustifySpaceBetween);
float midMaxOfMin = Math.max(Math.max(minLeft.y, minCenter.y), minRight.y);
Yoga.YGNodeStyleSetMinHeight(mNode, midMaxOfMin);
Yoga.YGNodeStyleSetMaxHeight(mNode, Float.MAX_VALUE);
Yoga.YGNodeStyleSetWidth(mNode, size.x);
Yoga.YGNodeStyleSetFlexGrow(mNode, 1);
Yoga.YGNodeStyleSetFlexShrink(mNode, 1);
Yoga.YGNodeStyleSetMaxWidth(tNode, maxTop.x);
Yoga.YGNodeStyleSetMaxHeight(tNode, maxTop.y);
Yoga.YGNodeStyleSetMinWidth(tNode, minTop.x);
Yoga.YGNodeStyleSetMinHeight(tNode, minTop.y);
Yoga.YGNodeStyleSetFlexGrow(tNode, 1);
Yoga.YGNodeStyleSetFlexShrink(tNode, 1);
Yoga.YGNodeStyleSetWidth(tNode, size.x);
Yoga.YGNodeStyleSetMaxWidth(bNode, maxBottom.x);
Yoga.YGNodeStyleSetMaxHeight(bNode, maxBottom.y);
Yoga.YGNodeStyleSetMinWidth(bNode, minBottom.x);
Yoga.YGNodeStyleSetMinHeight(bNode, minBottom.y);
Yoga.YGNodeStyleSetFlexGrow(bNode, 1);
Yoga.YGNodeStyleSetFlexShrink(bNode, 1);
Yoga.YGNodeStyleSetWidth(bNode, size.x);
Yoga.YGNodeStyleSetMaxWidth(lNode, maxLeft.x);
Yoga.YGNodeStyleSetMaxHeight(lNode, maxLeft.y);
Yoga.YGNodeStyleSetMinWidth(lNode, minLeft.x);
Yoga.YGNodeStyleSetMinHeight(lNode, minLeft.y);
Yoga.YGNodeStyleSetFlexGrow(lNode, 1);
Yoga.YGNodeStyleSetFlexShrink(lNode, 1);
Yoga.YGNodeStyleSetMinHeight(lNode, midMaxOfMin);
Yoga.YGNodeStyleSetMaxWidth(cNode, maxCenter.x);
Yoga.YGNodeStyleSetMaxHeight(cNode, maxCenter.y);
Yoga.YGNodeStyleSetMinWidth(cNode, minCenter.x);
Yoga.YGNodeStyleSetMinHeight(cNode, minCenter.y);
Yoga.YGNodeStyleSetFlexGrow(cNode, 1);
Yoga.YGNodeStyleSetFlexShrink(cNode, 1);
Yoga.YGNodeStyleSetMinHeight(cNode, midMaxOfMin);
Yoga.YGNodeStyleSetMaxWidth(rNode, maxRight.x);
Yoga.YGNodeStyleSetMaxHeight(rNode, maxRight.y);
Yoga.YGNodeStyleSetMinWidth(rNode, minRight.x);
Yoga.YGNodeStyleSetMinHeight(rNode, minRight.y);
Yoga.YGNodeStyleSetFlexGrow(rNode, 1);
Yoga.YGNodeStyleSetFlexShrink(rNode, 1);
Yoga.YGNodeStyleSetMinHeight(rNode, midMaxOfMin);
Yoga.nYGNodeCalculateLayout(rootNode, size.x, size.y, Yoga.YGDirectionLTR);
Vector2f d = new Vector2f(Yoga.YGNodeLayoutGetLeft(mNode), Yoga.YGNodeLayoutGetTop(mNode));
midRow.set(Yoga.YGNodeLayoutGetLeft(mNode), Yoga.YGNodeLayoutGetTop(mNode), Yoga.YGNodeLayoutGetWidth(mNode), Yoga.YGNodeLayoutGetHeight(mNode));
top.set(Yoga.YGNodeLayoutGetLeft(tNode), Yoga.YGNodeLayoutGetTop(tNode), Yoga.YGNodeLayoutGetWidth(tNode), Yoga.YGNodeLayoutGetHeight(tNode));
bottom.set(Yoga.YGNodeLayoutGetLeft(bNode), Yoga.YGNodeLayoutGetTop(bNode), Yoga.YGNodeLayoutGetWidth(bNode), Yoga.YGNodeLayoutGetHeight(bNode));
left.set(Yoga.YGNodeLayoutGetLeft(lNode) + d.x, Yoga.YGNodeLayoutGetTop(lNode) + d.y, Yoga.YGNodeLayoutGetWidth(lNode), Yoga.YGNodeLayoutGetHeight(lNode));
right.set(Yoga.YGNodeLayoutGetLeft(rNode) + d.x, Yoga.YGNodeLayoutGetTop(rNode) + d.y, Yoga.YGNodeLayoutGetWidth(rNode), Yoga.YGNodeLayoutGetHeight(rNode));
center.set(Yoga.YGNodeLayoutGetLeft(cNode) + d.x, Yoga.YGNodeLayoutGetTop(cNode) + d.y, Yoga.YGNodeLayoutGetWidth(cNode), Yoga.YGNodeLayoutGetHeight(cNode));
Yoga.YGNodeFree(rootNode);
Yoga.YGNodeFree(mNode);
Yoga.YGNodeFree(tNode);
Yoga.YGNodeFree(lNode);
Yoga.YGNodeFree(cNode);
Yoga.YGNodeFree(rNode);
Yoga.YGNodeFree(bNode);
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the update() method and the YGNodeCalculateLayout call, then inspect the calculated rectangles for rootNode, mNode, and its children under the stated min/max constraints. Done means the reproduced layout no longer contains the reported empty gaps between stretched nodes and the expected behavior is covered by a regression case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, java
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100