mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibWeb: Make foreignObject establish a containing block for abspos
Absolutely positioned elements inside SVG foreignObject were being positioned relative to an ancestor containing block outside the SVG, instead of relative to the foreignObject itself. Per a W3C resolution and the behavior of other browsers, foreignObject should establish a containing block for absolutely and fixed positioned elements. With this fix, the `has_abspos_with_external_containing_block` check in `set_needs_layout_update()` and the abspos preservation loop in `relayout_svg_root()` become dead code — remove both and simplify the ancestor loops. Rename related tests to reflect the new behavior. Fixes https://github.com/LadybirdBrowser/ladybird/issues/3241
This commit is contained in:
committed by
Alexander Kalenik
parent
fa49de8956
commit
b3231ea2a0
Notes:
github-actions[bot]
2026-02-17 15:49:36 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/b3231ea2a04 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7993 Reviewed-by: https://github.com/gmta
@@ -160,6 +160,11 @@ bool Node::establishes_an_absolute_positioning_containing_block() const
|
||||
if (is<Viewport>(*this))
|
||||
return true;
|
||||
|
||||
// https://github.com/w3c/fxtf-drafts/issues/307#issuecomment-499612420
|
||||
// foreignObject establishes a containing block for absolutely and fixed positioned elements.
|
||||
if (is_svg_foreign_object_box())
|
||||
return true;
|
||||
|
||||
return computed_values_establish_absolute_positioning_containing_block();
|
||||
}
|
||||
|
||||
@@ -1467,29 +1472,11 @@ void Node::set_needs_layout_update(DOM::SetNeedsLayoutReason reason)
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
auto has_abspos_with_external_containing_block = [](SVGSVGBox const& svg_box) {
|
||||
for (auto const* ancestor = svg_box.parent(); ancestor; ancestor = ancestor->parent()) {
|
||||
auto const* box = as_if<Box>(ancestor);
|
||||
if (!box)
|
||||
continue;
|
||||
for (auto const& abspos_child : box->contained_abspos_children()) {
|
||||
if (svg_box.is_inclusive_ancestor_of(abspos_child))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
||||
if (ancestor->m_needs_layout_update)
|
||||
break;
|
||||
ancestor->m_needs_layout_update = true;
|
||||
if (auto* svg_box = as_if<SVGSVGBox>(ancestor)) {
|
||||
// Absolutely positioned elements inside the SVG subtree whose containing
|
||||
// block is outside the SVG can't be properly relaid out during partial SVG
|
||||
// relayout — their layout depends on formatting contexts outside the subtree.
|
||||
if (has_abspos_with_external_containing_block(*svg_box))
|
||||
continue;
|
||||
document().mark_svg_root_as_needing_relayout(*svg_box);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user