diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 751f4631533..d6063ffbc0d 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2022, Andreas Kling + * Copyright (c) 2025, Jelle Raaijmakers * * SPDX-License-Identifier: BSD-2-Clause */ @@ -958,18 +959,6 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically float_box->margin_box_rect_in_root_coordinate_space = margin_box_rect_in_ancestor_coordinate_space(float_box->used_values, root()); } -// Returns whether the given box has the given ancestor on the path to root, ignoring the anonymous blocks. -static bool box_has_ancestor_in_non_anonymous_containing_block_chain(Box const* box, Box const& ancestor, Box const& root) -{ - Box const* current_ancestor = box ? box->non_anonymous_containing_block() : &root; - while (current_ancestor != &root) { - if (current_ancestor == &ancestor) - return true; - current_ancestor = current_ancestor->non_anonymous_containing_block(); - } - return false; -} - void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontally(Box const& child_box, AvailableSpace const& available_space) { auto& box_state = m_state.get_mutable(child_box); @@ -982,12 +971,18 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontal auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(box_state, root()); auto space_and_containing_margin = space_used_and_containing_margin_for_floats(box_in_root_rect.y()); available_width_within_containing_block -= space_and_containing_margin.left_used_space + space_and_containing_margin.right_used_space; - auto const& containing_box_state = m_state.get(*child_box.containing_block()); - if (box_has_ancestor_in_non_anonymous_containing_block_chain(space_and_containing_margin.matching_left_float_box, *child_box.non_anonymous_containing_block(), root())) - x = space_and_containing_margin.left_used_space; - else - // If the floating box doesn't share a containing block with the child box, the child box margin should overlap with the width of the floating box. - x = max(space_and_containing_margin.left_used_space - containing_box_state.margin_left, 0); + x = space_and_containing_margin.left_used_space; + + // All non-anonymous containing blocks that are ancestors of the child box, but are not ancestors of the left + // float box, might have left margins set that overlap with the used float space. + if (space_and_containing_margin.matching_left_float_box) { + Box const* current_ancestor = child_box.non_anonymous_containing_block(); + while (!current_ancestor->is_ancestor_of(*space_and_containing_margin.matching_left_float_box)) { + x -= m_state.get(*current_ancestor).margin_left; + current_ancestor = current_ancestor->non_anonymous_containing_block(); + } + x = max(x, 0); + } } if (child_box.containing_block()->computed_values().text_align() == CSS::TextAlign::LibwebCenter) { diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.txt b/Tests/LibWeb/Layout/expected/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.txt new file mode 100644 index 00000000000..ae157e26e1d --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.txt @@ -0,0 +1,37 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x48 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x22 children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline + BlockContainer at (8,8) content-size 100x40 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer at (109,9) content-size 682x20 children: not-inline + BlockContainer <(anonymous)> at (109,9) content-size 682x0 children: inline + TextNode <#text> + BlockContainer
at (109,9) content-size 682x20 children: not-inline + BlockContainer <(anonymous)> at (109,9) content-size 682x0 children: inline + TextNode <#text> + BlockContainer at (110,10) content-size 680x18 [BFC] children: inline + frag 0 from TextNode start: 0, length: 3, rect: [110,10 27.15625x18] baseline: 13.796875 + "foo" + TextNode <#text> + BlockContainer <(anonymous)> at (109,29) content-size 682x0 children: inline + TextNode <#text> + BlockContainer <(anonymous)> at (109,29) content-size 682x0 children: inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,30) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x48] + PaintableWithLines (BlockContainer) [8,8 784x22] + PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0] + PaintableWithLines (BlockContainer
#a) [8,8 100x40] + PaintableWithLines (BlockContainer
#b) [108,8 684x22] + PaintableWithLines (BlockContainer(anonymous)) [109,9 682x0] + PaintableWithLines (BlockContainer
) [109,9 682x20] + PaintableWithLines (BlockContainer(anonymous)) [109,9 682x0] + PaintableWithLines (BlockContainer
#c) [109,9 682x20] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [109,29 682x0] + PaintableWithLines (BlockContainer(anonymous)) [109,29 682x0] + PaintableWithLines (BlockContainer(anonymous)) [8,30 784x0] diff --git a/Tests/LibWeb/Layout/input/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.html b/Tests/LibWeb/Layout/input/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.html new file mode 100644 index 00000000000..79e549287c9 --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/block-with-hidden-overflow-after-float-and-margin-left.html @@ -0,0 +1,23 @@ + + +
+
+
+
foo
+
+