From 0ced74cde39a88a2173f11b166ae1b0a4d130358 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Mon, 19 Jun 2023 18:51:00 +0200 Subject: [PATCH] Fix positioning of statically positioned absolute child of inline box --- components/layout_2020/flow/inline.rs | 14 +++++++++++--- components/layout_2020/positioned.rs | 17 ++++++++++++----- tests/wpt/meta/MANIFEST.json | 17 +++++++++++++++++ .../abspos/static-inside-inline-block-ref.html | 11 +++++++++++ .../CSS2/abspos/static-inside-inline-block.html | 12 ++++++++++++ 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block-ref.html create mode 100644 tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block.html diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index aba8790987a..e713d9c2a8e 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -659,13 +659,20 @@ fn layout_atomic( containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); - // FIXME: Do we need to adjust the static position of the hoisted fragments in the positioning - // context somewhere near here? + + let collects_for_nearest_positioned_ancestor = ifc + .positioning_context + .collects_for_nearest_positioned_ancestor(); + let mut child_positioning_context = + PositioningContext::new_for_subtree(collects_for_nearest_positioned_ancestor); let independent_layout = non_replaced.layout( layout_context, - ifc.positioning_context, + &mut child_positioning_context, &containing_block_for_children, ); + child_positioning_context + .adjust_static_position_of_hoisted_fragments_with_offset(&start_corner); + ifc.positioning_context.append(child_positioning_context); // https://drafts.csswg.org/css2/visudet.html#block-root-margin let tentative_block_size = box_size @@ -685,6 +692,7 @@ fn layout_atomic( inline: inline_size, }, }; + BoxFragment::new( non_replaced.base_fragment_info, non_replaced.style.clone(), diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index b1ab687a4e9..07831f8dbf8 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -166,20 +166,27 @@ impl PositioningContext { &mut self, parent_fragment: &Fragment, ) { - let fragment_rect = match &parent_fragment { - Fragment::Box(b) | Fragment::Float(b) => &b.content_rect, + let start_offset = match &parent_fragment { + Fragment::Box(b) | Fragment::Float(b) => &b.content_rect.start_corner, Fragment::AbsoluteOrFixedPositioned(_) => return, - Fragment::Anonymous(a) => &a.rect, + Fragment::Anonymous(a) => &a.rect.start_corner, _ => unreachable!(), }; + self.adjust_static_position_of_hoisted_fragments_with_offset(start_offset); + } + /// See documentation for [adjust_static_position_of_hoisted_fragments]. + pub(crate) fn adjust_static_position_of_hoisted_fragments_with_offset( + &mut self, + start_offset: &Vec2, + ) { let update_fragment_if_needed = |hoisted_fragment: &mut HoistedAbsolutelyPositionedBox| { let mut fragment = hoisted_fragment.fragment.borrow_mut(); if let AbsoluteBoxOffsets::StaticStart { start } = &mut fragment.box_offsets.inline { - *start += fragment_rect.start_corner.inline; + *start += start_offset.inline; } if let AbsoluteBoxOffsets::StaticStart { start } = &mut fragment.box_offsets.block { - *start += fragment_rect.start_corner.block; + *start += start_offset.block; } }; diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index f0b065a74d8..d39c79550ed 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -31605,6 +31605,19 @@ {} ] ], + "static-inside-inline-block.html": [ + "327e8e6dacdeabb4d2d57ab700d80f966ccde76b", + [ + null, + [ + [ + "/css/CSS2/abspos/static-inside-inline-block-ref.html", + "==" + ] + ], + {} + ] + ], "static-inside-table-cell.html": [ "712bfbaf1e8f2d6a7a8fdd8dfa65792770f004e3", [ @@ -355090,6 +355103,10 @@ "hypothetical-inline-alone-on-second-line-ref.html": [ "1ceebb0f7e39896003508a769c772cc6e6bf54cd", [] + ], + "static-inside-inline-block-ref.html": [ + "e76a2ccb972a2c056ffdd6380e60e5590b87b36e", + [] ] }, "backgrounds": { diff --git a/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block-ref.html b/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block-ref.html new file mode 100644 index 00000000000..e76a2ccb972 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block-ref.html @@ -0,0 +1,11 @@ + +Static position inside inline-block + + + +

Test passes if there is a filled green square and no red.

+
+
+
+
+
diff --git a/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block.html b/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block.html new file mode 100644 index 00000000000..327e8e6dacd --- /dev/null +++ b/tests/wpt/web-platform-tests/css/CSS2/abspos/static-inside-inline-block.html @@ -0,0 +1,12 @@ + +Static position inside inline-block + + + + +

Test passes if there is a filled green square and no red.

+
+
+
+
+