diff --git a/src/Layout.c b/src/Layout.c index 8581ad27..60bb0b1a 100644 --- a/src/Layout.c +++ b/src/Layout.c @@ -394,6 +394,26 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) { // You never want to go smaller than padding getPaddingAndBorderAxis(child, crossAxis) ); + } else if (getPositionType(child) == CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (int ii = 0; ii < 2; ii++) { + css_flex_direction_t axis = ii ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node->layout.dimensions[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child->layout.dimensions[dim[axis]] = fmaxf( + node->layout.dimensions[dim[axis]] - + getPaddingAndBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis]), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } } } diff --git a/src/Layout.js b/src/Layout.js index 27c3cf29..16c567a2 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -269,6 +269,26 @@ var computeLayout = (function() { // You never want to go smaller than padding getPaddingAndBorderAxis(child, crossAxis) ); + } else if (getPositionType(child) == CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (var/*int*/ ii = 0; ii < 2; ii++) { + var/*css_flex_direction_t*/ axis = ii ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node.layout[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child.layout[dim[axis]] = fmaxf( + node.layout[dim[axis]] - + getPaddingAndBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis]), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } } } diff --git a/src/__tests__/Layout-test.c b/src/__tests__/Layout-test.c index b6ae7e4a..9b310fac 100644 --- a/src/__tests__/Layout-test.c +++ b/src/__tests__/Layout-test.c @@ -3165,6 +3165,99 @@ int main() test("should layout with position: absolute and another sibling", root_node, root_layout); } + + { + css_node_t *root_node = new_test_css_node(); + { + css_node_t *node_0 = root_node; + node_0->style.dimensions[CSS_WIDTH] = 100; + node_0->style.dimensions[CSS_HEIGHT] = 100; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->style.position_type = CSS_POSITION_ABSOLUTE; + node_1->style.position[CSS_TOP] = 0; + node_1->style.position[CSS_BOTTOM] = 20; + } + } + + css_node_t *root_layout = new_test_css_node(); + { + css_node_t *node_0 = root_layout; + node_0->layout.position[CSS_TOP] = 0; + node_0->layout.position[CSS_LEFT] = 0; + node_0->layout.dimensions[CSS_WIDTH] = 100; + node_0->layout.dimensions[CSS_HEIGHT] = 100; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->layout.position[CSS_TOP] = 0; + node_1->layout.position[CSS_LEFT] = 0; + node_1->layout.dimensions[CSS_WIDTH] = 0; + node_1->layout.dimensions[CSS_HEIGHT] = 80; + } + } + + test("should layout with position: absolute, bottom", root_node, root_layout); + } + + { + css_node_t *root_node = new_test_css_node(); + { + css_node_t *node_0 = root_node; + node_0->style.dimensions[CSS_WIDTH] = 200; + node_0->style.dimensions[CSS_HEIGHT] = 200; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->style.justify_content = CSS_JUSTIFY_CENTER; + node_1->style.position_type = CSS_POSITION_ABSOLUTE; + node_1->style.position[CSS_LEFT] = 0; + node_1->style.position[CSS_TOP] = 0; + node_1->style.position[CSS_RIGHT] = 0; + node_1->style.position[CSS_BOTTOM] = 0; + init_css_node_children(node_1, 1); + { + css_node_t *node_2; + node_2 = node_1->get_child(node_1->context, 0); + node_2->style.dimensions[CSS_WIDTH] = 100; + node_2->style.dimensions[CSS_HEIGHT] = 100; + } + } + } + + css_node_t *root_layout = new_test_css_node(); + { + css_node_t *node_0 = root_layout; + node_0->layout.position[CSS_TOP] = 0; + node_0->layout.position[CSS_LEFT] = 0; + node_0->layout.dimensions[CSS_WIDTH] = 200; + node_0->layout.dimensions[CSS_HEIGHT] = 200; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->layout.position[CSS_TOP] = 0; + node_1->layout.position[CSS_LEFT] = 0; + node_1->layout.dimensions[CSS_WIDTH] = 200; + node_1->layout.dimensions[CSS_HEIGHT] = 200; + init_css_node_children(node_1, 1); + { + css_node_t *node_2; + node_2 = node_1->get_child(node_1->context, 0); + node_2->layout.position[CSS_TOP] = 50; + node_2->layout.position[CSS_LEFT] = 0; + node_2->layout.dimensions[CSS_WIDTH] = 100; + node_2->layout.dimensions[CSS_HEIGHT] = 100; + } + } + } + + test("should layout with complicated position: absolute and justifyContent: center combo", root_node, root_layout); + } /** END_GENERATED **/ return tests_finished(); } diff --git a/src/__tests__/Layout-test.js b/src/__tests__/Layout-test.js index f72cab8d..89eee5f3 100755 --- a/src/__tests__/Layout-test.js +++ b/src/__tests__/Layout-test.js @@ -973,5 +973,31 @@ describe('Layout', function() { ); }); + it('should layout with position: absolute, bottom', function() { + testLayout( + {style: {width: 100, height: 100}, children: [ + {style: {position: 'absolute', top: 0, bottom: 20}} + ]}, + {width: 100, height: 100, top: 0, left: 0, children: [ + {width: 0, height: 80, top: 0, left: 0} + ]} + ); + }); + + it('should layout with complicated position: absolute and justifyContent: center combo', function() { + testLayout( + {style: {width: 200, height: 200}, children: [ + {style: {position: 'absolute', justifyContent: 'center', top: 0, left: 0, right: 0, bottom: 0}, children: [ + {style: {width: 100, height: 100}} + ]} + ]}, + {width: 200, height: 200, top: 0, left: 0, children: [ + {width: 200, height: 200, top: 0, left: 0, children: [ + {width: 100, height: 100, top: 50, left: 0} + ]} + ]} + ); + }); + });