mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 09:45:06 +02:00
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
61 lines
2.3 KiB
HTML
61 lines
2.3 KiB
HTML
<!DOCTYPE html>
|
|
<script src="../include.js"></script>
|
|
<style>
|
|
.container {
|
|
position: relative;
|
|
width: 200px;
|
|
height: 200px;
|
|
}
|
|
.abspos {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
width: 50px;
|
|
height: 50px;
|
|
background: green;
|
|
}
|
|
</style>
|
|
<div class="container">
|
|
<svg width="100" height="100">
|
|
<foreignObject width="100" height="100">
|
|
<div class="abspos" id="abspos"></div>
|
|
</foreignObject>
|
|
</svg>
|
|
</div>
|
|
<script>
|
|
asyncTest(done => {
|
|
// Force initial layout and capture "before" values without any DOM mutations.
|
|
// (println modifies the DOM, which would trigger full relayout instead of partial SVG relayout)
|
|
document.body.offsetWidth;
|
|
const absposBefore = document.getElementById("abspos").getBoundingClientRect();
|
|
|
|
// Change the abspos element's size via inline style.
|
|
// Since this element is inside the SVG subtree (via foreignObject),
|
|
// set_needs_layout_update() breaks at SVGSVGBox and triggers partial SVG relayout.
|
|
// The abspos element's containing block is the foreignObject itself, so the size
|
|
// change should take effect during partial SVG relayout.
|
|
const abspos = document.getElementById("abspos");
|
|
abspos.style.width = "100px";
|
|
abspos.style.height = "100px";
|
|
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
const absposAfter = document.getElementById("abspos").getBoundingClientRect();
|
|
|
|
// Now it's safe to print (layout observations are done)
|
|
println(`Before SVG relayout:`);
|
|
println(` abspos width: ${absposBefore.width}`);
|
|
println(` abspos height: ${absposBefore.height}`);
|
|
println(`After SVG relayout:`);
|
|
println(` abspos width: ${absposAfter.width}`);
|
|
println(` abspos height: ${absposAfter.height}`);
|
|
println(`Abspos size correctly updated:`);
|
|
println(` width changed to 100: ${absposAfter.width === 100}`);
|
|
println(` height changed to 100: ${absposAfter.height === 100}`);
|
|
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
</script>
|