Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
490 changes: 490 additions & 0 deletions integration_tests/specs/css/css-flexbox/flex-gap-sizing.ts

Large diffs are not rendered by default.

30 changes: 25 additions & 5 deletions webf/lib/src/rendering/flex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4027,14 +4027,26 @@ class RenderFlexLayout extends RenderLayoutBox {
}
}

final double childScrollableMain = preSiblingsMainSize +
(_isHorizontalFlexDirection
? childScrollableSize.width + childOffsetX
: childScrollableSize.height + childOffsetY);
final double childScrollableCross = _isHorizontalFlexDirection
final double childBoxMainSize = _isHorizontalFlexDirection ? child.size.width : child.size.height;
final double childBoxCrossSize = _isHorizontalFlexDirection ? child.size.height : child.size.width;
final double childMainOffset = _isHorizontalFlexDirection ? childOffsetX : childOffsetY;
final double childCrossOffset = _isHorizontalFlexDirection ? childOffsetY : childOffsetX;
final double childScrollableMainExtent = _isHorizontalFlexDirection
? childScrollableSize.width + childOffsetX
: childScrollableSize.height + childOffsetY;
final double childScrollableCrossExtent = _isHorizontalFlexDirection
? childScrollableSize.height + childOffsetY
: childScrollableSize.width + childOffsetX;

// The child's extent must cover at least its offset border-box.
// child.scrollableSize may only cover padding-box, but offsets (margin/relative/transform)
// still need to be preserved so negative offsets don't create phantom trailing scroll range.
final double childScrollableMain = preSiblingsMainSize +
math.max(childBoxMainSize + childMainOffset, childScrollableMainExtent);
final double childScrollableCross = math.max(
childBoxCrossSize + childCrossOffset,
childScrollableCrossExtent);

maxScrollableMainSizeOfLine = math.max(maxScrollableMainSizeOfLine, childScrollableMain);
maxScrollableCrossSizeInLine = math.max(maxScrollableCrossSizeInLine, childScrollableCross);

Expand All @@ -4048,6 +4060,10 @@ class RenderFlexLayout extends RenderLayoutBox {
}
}
preSiblingsMainSize += childMainSize;
// Add main-axis gap between items (not after the last item).
if (runChild != runChildren.last) {
preSiblingsMainSize += _getMainAxisGap();
}
}

// Max scrollable cross size of all the children in the line.
Expand All @@ -4056,6 +4072,10 @@ class RenderFlexLayout extends RenderLayoutBox {
scrollableMainSizeOfLines.add(maxScrollableMainSizeOfLine);
scrollableCrossSizeOfLines.add(maxScrollableCrossSizeOfLine);
preLinesCrossSize += runMetric.crossAxisExtent;
// Add cross-axis gap between flex lines (not after the last line).
if (runMetric != runMetrics.last) {
preLinesCrossSize += _getCrossAxisGap();
}
}

// Max scrollable main size of all lines.
Expand Down
67 changes: 53 additions & 14 deletions webf/test/src/rendering/flex_item_width_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ void main() {
});

group('Flex Item Width', () {
testWidgets('block elements in flex container should not stretch to parent width', (WidgetTester tester) async {
testWidgets(
'block elements in flex container should not stretch to parent width',
(WidgetTester tester) async {
final prepared = await WebFWidgetTestUtils.prepareWidgetTest(
tester: tester,
controllerName: 'flex-item-width-${DateTime.now().millisecondsSinceEpoch}',
controllerName:
'flex-item-width-${DateTime.now().millisecondsSinceEpoch}',
html: '''
<html>
<body style="margin: 0; padding: 0;">
Expand All @@ -53,30 +56,32 @@ void main() {
final item1 = prepared.getElementById('item1');
final item2 = prepared.getElementById('item2');
final item3 = prepared.getElementById('item3');

// Container should be 600px wide
expect(container.offsetWidth, equals(600));

// Items should size to their content, not stretch to 600px
expect(item1.offsetWidth, lessThan(600));
expect(item2.offsetWidth, lessThan(600));
expect(item3.offsetWidth, lessThan(600));

// Items should have different widths based on their content
expect(item1.offsetWidth, isNot(equals(item2.offsetWidth)));
expect(item2.offsetWidth, isNot(equals(item3.offsetWidth)));

// Debug output
print('Container width: ${container.offsetWidth}');
print('Item 1 width: ${item1.offsetWidth}');
print('Item 2 width: ${item2.offsetWidth}');
print('Item 3 width: ${item3.offsetWidth}');
});

testWidgets('block elements with explicit width should respect it', (WidgetTester tester) async {
testWidgets('block elements with explicit width should respect it',
(WidgetTester tester) async {
final prepared = await WebFWidgetTestUtils.prepareWidgetTest(
tester: tester,
controllerName: 'flex-item-explicit-width-${DateTime.now().millisecondsSinceEpoch}',
controllerName:
'flex-item-explicit-width-${DateTime.now().millisecondsSinceEpoch}',
html: '''
<html>
<body style="margin: 0; padding: 0;">
Expand All @@ -93,10 +98,10 @@ void main() {

final item1 = prepared.getElementById('item1');
final item2 = prepared.getElementById('item2');

// Item with explicit width should be 100px
expect(item1.offsetWidth, equals(100));

// Item without width should size to content
expect(item2.offsetWidth, lessThan(600));
expect(item2.offsetWidth, isNot(equals(100)));
Expand All @@ -105,7 +110,8 @@ void main() {
testWidgets('flex-grow should expand items', (WidgetTester tester) async {
final prepared = await WebFWidgetTestUtils.prepareWidgetTest(
tester: tester,
controllerName: 'flex-grow-test-${DateTime.now().millisecondsSinceEpoch}',
controllerName:
'flex-grow-test-${DateTime.now().millisecondsSinceEpoch}',
html: '''
<html>
<body style="margin: 0; padding: 0;">
Expand All @@ -122,15 +128,48 @@ void main() {

final item1 = prepared.getElementById('item1');
final item2 = prepared.getElementById('item2');

// Item 2 should size to content
final item2ContentWidth = item2.offsetWidth;

// Item 1 with flex-grow should take remaining space
expect(item1.offsetWidth, equals(600 - item2ContentWidth));

// Total should equal container width
expect(item1.offsetWidth + item2.offsetWidth, equals(600));
});

testWidgets(
'negative start-side offset should not create phantom trailing scroll range',
(WidgetTester tester) async {
final prepared = await WebFWidgetTestUtils.prepareWidgetTest(
tester: tester,
controllerName:
'flex-negative-offset-scroll-${DateTime.now().millisecondsSinceEpoch}',
html: '''
<html>
<body style="margin: 0; padding: 0;">
<div id="relative" style="display: flex; width: 200px; overflow: auto;">
<div style="flex: 0 0 150px; height: 20px; background: #f66;"></div>
<div style="flex: 0 0 150px; height: 20px; background: #66f; position: relative; left: -100px;"></div>
</div>
<div id="transform" style="display: flex; width: 200px; overflow: auto; margin-top: 8px;">
<div style="flex: 0 0 150px; height: 20px; background: #6c6;"></div>
<div style="flex: 0 0 150px; height: 20px; background: #fc6; transform: translateX(-100px);"></div>
</div>
</body>
</html>
''',
);

await tester.pump();

final relative = prepared.getElementById('relative');
final transform = prepared.getElementById('transform');

// Both containers should end at 200px; shifted children should not add trailing blank scroll area.
expect(relative.scrollWidth, moreOrLessEquals(200, epsilon: 1));
expect(transform.scrollWidth, moreOrLessEquals(200, epsilon: 1));
});
});
}
Loading