Skip to content

Commit f99b57f

Browse files
Fix wrong size propogation for absolute elements (#878)
* Fix wrong size propogation for absolute elements * Add fix+test for grid and test block --------- Co-authored-by: Nico Burns <[email protected]>
1 parent df1ba34 commit f99b57f

13 files changed

+834
-6
lines changed

src/compute/block.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ fn perform_absolute_layout_on_absolute_children(
653653
known_dimensions = known_dimensions.maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size);
654654
}
655655

656-
let layout_output = tree.perform_child_layout(
656+
let measured_size = tree.measure_child_size_both(
657657
item.node_id,
658658
known_dimensions,
659659
area_size.map(Some),
@@ -664,9 +664,21 @@ fn perform_absolute_layout_on_absolute_children(
664664
SizingMode::ContentSize,
665665
Line::FALSE,
666666
);
667-
let measured_size = layout_output.size;
667+
668668
let final_size = known_dimensions.unwrap_or(measured_size).maybe_clamp(min_size, max_size);
669669

670+
let layout_output = tree.perform_child_layout(
671+
item.node_id,
672+
final_size.map(Some),
673+
area_size.map(Some),
674+
Size {
675+
width: AvailableSpace::Definite(area_width.maybe_clamp(min_size.width, max_size.width)),
676+
height: AvailableSpace::Definite(area_height.maybe_clamp(min_size.height, max_size.height)),
677+
},
678+
SizingMode::ContentSize,
679+
Line::FALSE,
680+
);
681+
670682
let non_auto_margin = Rect {
671683
left: if left.is_some() { margin.left.unwrap_or(0.0) } else { 0.0 },
672684
right: if right.is_some() { margin.right.unwrap_or(0.0) } else { 0.0 },

src/compute/flexbox.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,7 +2145,7 @@ fn perform_absolute_layout_on_absolute_children(
21452145
known_dimensions.height = Some(f32_max(new_height_raw, 0.0));
21462146
known_dimensions = known_dimensions.maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size);
21472147
}
2148-
let layout_output = tree.perform_child_layout(
2148+
let measured_size = tree.measure_child_size_both(
21492149
child,
21502150
known_dimensions,
21512151
constants.node_inner_size,
@@ -2156,9 +2156,20 @@ fn perform_absolute_layout_on_absolute_children(
21562156
SizingMode::InherentSize,
21572157
Line::FALSE,
21582158
);
2159-
let measured_size = layout_output.size;
21602159
let final_size = known_dimensions.unwrap_or(measured_size).maybe_clamp(min_size, max_size);
21612160

2161+
let layout_output = tree.perform_child_layout(
2162+
child,
2163+
final_size.map(Some),
2164+
constants.node_inner_size,
2165+
Size {
2166+
width: AvailableSpace::Definite(container_width.maybe_clamp(min_size.width, max_size.width)),
2167+
height: AvailableSpace::Definite(container_height.maybe_clamp(min_size.height, max_size.height)),
2168+
},
2169+
SizingMode::InherentSize,
2170+
Line::FALSE,
2171+
);
2172+
21622173
let non_auto_margin = margin.map(|m| m.unwrap_or(0.0));
21632174

21642175
let free_space = Size {

src/compute/grid/alignment.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,32 @@ pub(super) fn align_and_position_item(
199199

200200
// Layout node
201201
drop(style);
202+
203+
let size = if position == Position::Absolute && (width.is_none() || height.is_none()) {
204+
tree.measure_child_size_both(
205+
node,
206+
Size { width, height },
207+
grid_area_size.map(Option::Some),
208+
grid_area_minus_item_margins_size.map(AvailableSpace::Definite),
209+
SizingMode::InherentSize,
210+
Line::FALSE,
211+
)
212+
.map(Some)
213+
} else {
214+
Size { width, height }
215+
};
216+
202217
let layout_output = tree.perform_child_layout(
203218
node,
204-
Size { width, height },
219+
size,
205220
grid_area_size.map(Option::Some),
206221
grid_area_minus_item_margins_size.map(AvailableSpace::Definite),
207222
SizingMode::InherentSize,
208223
Line::FALSE,
209224
);
210225

211226
// Resolve final size
212-
let Size { width, height } = Size { width, height }.unwrap_or(layout_output.size).maybe_clamp(min_size, max_size);
227+
let Size { width, height } = size.unwrap_or(layout_output.size).maybe_clamp(min_size, max_size);
213228

214229
let (x, x_margin) = align_item_within_area(
215230
Line { start: grid_area.left, end: grid_area.right },

src/tree/traits.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,33 @@ pub(crate) trait LayoutPartialTreeExt: LayoutPartialTree {
349349
.get_abs(axis)
350350
}
351351

352+
/// Compute the size of the node given the specified constraints
353+
#[inline(always)]
354+
#[allow(clippy::too_many_arguments)]
355+
fn measure_child_size_both(
356+
&mut self,
357+
node_id: NodeId,
358+
known_dimensions: Size<Option<f32>>,
359+
parent_size: Size<Option<f32>>,
360+
available_space: Size<AvailableSpace>,
361+
sizing_mode: SizingMode,
362+
vertical_margins_are_collapsible: Line<bool>,
363+
) -> Size<f32> {
364+
self.compute_child_layout(
365+
node_id,
366+
LayoutInput {
367+
known_dimensions,
368+
parent_size,
369+
available_space,
370+
sizing_mode,
371+
axis: RequestedAxis::Both,
372+
run_mode: RunMode::ComputeSize,
373+
vertical_margins_are_collapsible,
374+
},
375+
)
376+
.size
377+
}
378+
352379
/// Perform a full layout on the node given the specified constraints
353380
#[inline(always)]
354381
fn perform_child_layout(
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<script src="../../scripts/gentest/test_helper.js"></script>
5+
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
6+
<title>
7+
Test description
8+
</title>
9+
</head>
10+
<body>
11+
12+
<div id="test-root" style="width: 300px; height: 110px; position: relative; display: block;">
13+
<div style="position: absolute; top: 40px; left: 50px; display: flex; flex-direction: column;">
14+
<div style="width: 200px; height: 10px;"></div>
15+
<div style="width: 100%; height: 10px;"></div>
16+
<div style="width: 100%; height: 10px; display: flex;">
17+
<div style="width: 10px; height: 10px;"></div>
18+
</div>
19+
</div>
20+
</div>
21+
22+
</body>
23+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<script src="../../scripts/gentest/test_helper.js"></script>
5+
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
6+
<title>
7+
Test description
8+
</title>
9+
</head>
10+
<body>
11+
12+
<div id="test-root" style="width: 300px; height: 110px; position: relative;">
13+
<div style="position: absolute; top: 40px; left: 50px; display: flex; flex-direction: column;">
14+
<div style="width: 200px; height: 10px;"></div>
15+
<div style="width: 100%; height: 10px;"></div>
16+
<div style="width: 100%; height: 10px; display: flex;">
17+
<div style="width: 10px; height: 10px;"></div>
18+
</div>
19+
</div>
20+
</div>
21+
22+
</body>
23+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<script src="../../scripts/gentest/test_helper.js"></script>
5+
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
6+
<title>
7+
Test description
8+
</title>
9+
</head>
10+
<body>
11+
12+
<div id="test-root" style="width: 300px; height: 110px; position: relative; display: grid;">
13+
<div style="position: absolute; top: 40px; left: 50px; display: flex; flex-direction: column;">
14+
<div style="width: 200px; height: 10px;"></div>
15+
<div style="width: 100%; height: 10px;"></div>
16+
<div style="width: 100%; height: 10px; display: flex;">
17+
<div style="width: 10px; height: 10px;"></div>
18+
</div>
19+
</div>
20+
</div>
21+
22+
</body>
23+
</html>

0 commit comments

Comments
 (0)