Resolve static positions after final layout repairs
This commit is contained in:
1 parent
d55e48a10f
commit
3fe624703b
1 file changed
+73
-11
@@ -2962,13 +2962,6 @@ fn layout_dom_once(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !static_position_candidates.is_empty() {
|
|
||||||
let _ = taffy_tree.compute_layout_with_measure(taffy_root, available, &mut measure);
|
|
||||||
resolve_static_positions_and_reparent(
|
|
||||||
&mut taffy_tree,
|
|
||||||
&static_position_candidates,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let _ = taffy_tree.compute_layout_with_measure(taffy_root, available, &mut measure);
|
let _ = taffy_tree.compute_layout_with_measure(taffy_root, available, &mut measure);
|
||||||
if repair_intrinsic_column_flex_negative_margins(
|
if repair_intrinsic_column_flex_negative_margins(
|
||||||
&mut taffy_tree,
|
&mut taffy_tree,
|
||||||
@@ -3065,16 +3058,28 @@ fn layout_dom_once(
|
|||||||
&mut measure,
|
&mut measure,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
// A fully-auto positioned axis uses the box's static position
|
||||||
#[cfg(not(feature = "paint"))]
|
// in its original formatting context. Harvest that coordinate
|
||||||
{
|
// only after every intrinsic/table/fragmentation repair has
|
||||||
|
// produced final in-flow geometry; otherwise reparenting pins
|
||||||
|
// the box to a stale preliminary document offset and can
|
||||||
|
// manufacture scrolling overflow. The resolver snapshots all
|
||||||
|
// candidates before changing any parent, preserving nested
|
||||||
|
// static-position candidates.
|
||||||
if !static_position_candidates.is_empty() {
|
if !static_position_candidates.is_empty() {
|
||||||
let _ = taffy_tree.compute_layout(taffy_root, available);
|
|
||||||
resolve_static_positions_and_reparent(
|
resolve_static_positions_and_reparent(
|
||||||
&mut taffy_tree,
|
&mut taffy_tree,
|
||||||
&static_position_candidates,
|
&static_position_candidates,
|
||||||
);
|
);
|
||||||
|
let _ = taffy_tree.compute_layout_with_measure(
|
||||||
|
taffy_root,
|
||||||
|
available,
|
||||||
|
&mut measure,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "paint"))]
|
||||||
|
{
|
||||||
let _ = taffy_tree.compute_layout(taffy_root, available);
|
let _ = taffy_tree.compute_layout(taffy_root, available);
|
||||||
if repair_intrinsic_column_flex_negative_margins(
|
if repair_intrinsic_column_flex_negative_margins(
|
||||||
&mut taffy_tree,
|
&mut taffy_tree,
|
||||||
@@ -3142,6 +3147,16 @@ fn layout_dom_once(
|
|||||||
) {
|
) {
|
||||||
let _ = taffy_tree.compute_layout(taffy_root, available);
|
let _ = taffy_tree.compute_layout(taffy_root, available);
|
||||||
}
|
}
|
||||||
|
// Keep the no-paint geometry path in the same final-position
|
||||||
|
// contract as screenshots: static coordinates are resolved
|
||||||
|
// after every pass that can move in-flow placeholders.
|
||||||
|
if !static_position_candidates.is_empty() {
|
||||||
|
resolve_static_positions_and_reparent(
|
||||||
|
&mut taffy_tree,
|
||||||
|
&static_position_candidates,
|
||||||
|
);
|
||||||
|
let _ = taffy_tree.compute_layout(taffy_root, available);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sync_resolved_percentage_padding(
|
sync_resolved_percentage_padding(
|
||||||
&taffy_tree,
|
&taffy_tree,
|
||||||
@@ -9435,6 +9450,53 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn static_positions_use_final_post_repair_geometry_without_phantom_overflow() {
|
||||||
|
let tree = parse_html(
|
||||||
|
r#"<style>
|
||||||
|
html,body{margin:0}
|
||||||
|
#columns{columns:3;width:630px;column-gap:30px}
|
||||||
|
#columns > div{height:100px;break-inside:avoid}
|
||||||
|
#holder{height:20px}
|
||||||
|
#outer{position:absolute;width:40px;height:40px}
|
||||||
|
#wrapper{margin-top:10px;height:20px}
|
||||||
|
#nested{position:absolute;width:5px;height:5px}
|
||||||
|
</style>
|
||||||
|
<div id="columns">
|
||||||
|
<div></div><div></div><div></div>
|
||||||
|
<div></div><div></div><div></div>
|
||||||
|
</div>
|
||||||
|
<div id="holder">
|
||||||
|
<div id="outer"><div id="wrapper"><div id="nested"></div></div></div>
|
||||||
|
</div>"#,
|
||||||
|
);
|
||||||
|
let laid = layout_dom(&tree, (800.0, 400.0));
|
||||||
|
let rect = |name| laid.rects[&tree.get_element_by_id(name).unwrap()];
|
||||||
|
let columns = rect("columns");
|
||||||
|
let holder = rect("holder");
|
||||||
|
let outer = rect("outer");
|
||||||
|
let wrapper = rect("wrapper");
|
||||||
|
let nested = rect("nested");
|
||||||
|
|
||||||
|
assert!((columns.height - 200.0).abs() < 0.01, "{columns:?}");
|
||||||
|
assert!((holder.y - 200.0).abs() < 0.01, "{holder:?}");
|
||||||
|
assert!(
|
||||||
|
(outer.y - holder.y).abs() < 0.01,
|
||||||
|
"outer static position was harvested before multicol repair: \
|
||||||
|
holder={holder:?} outer={outer:?}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
(nested.y - wrapper.y).abs() < 0.01,
|
||||||
|
"nested static-position candidate changed while reparenting its ancestor: \
|
||||||
|
wrapper={wrapper:?} nested={nested:?}"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
laid.scrolling_content_size(&tree, (800.0, 400.0)),
|
||||||
|
(800.0, 400.0),
|
||||||
|
"a stale preliminary static position must not create scrolling overflow"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multicol_does_not_atomize_breakable_prose_boxes() {
|
fn multicol_does_not_atomize_breakable_prose_boxes() {
|
||||||
let tree = parse_html(
|
let tree = parse_html(
|
||||||
|
|||||||
Reference in new issue
Block a user