diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/clear-both-from-inline-formatting-context.txt b/Tests/LibWeb/Layout/expected/block-and-inline/clear-both-from-inline-formatting-context.txt new file mode 100644 index 0000000000..390bb02fe6 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/clear-both-from-inline-formatting-context.txt @@ -0,0 +1,23 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x0 children: not-inline + BlockContainer
at (8,8) content-size 784x0 children: inline + TextNode <#text> + BlockContainer at (8,29.4375) content-size 28.53125x34.9375 floating [BFC] children: inline + line 0 width: 28.53125, height: 34.9375, bottom: 34.9375, baseline: 27.0625 + frag 0 from TextNode start: 0, length: 1, rect: [8,29.4375 28.53125x34.9375] + "A" + TextNode <#text> + TextNode <#text> + BlockContainer at (773.3125,29.4375) content-size 18.6875x34.9375 floating [BFC] children: inline + line 0 width: 18.6875, height: 34.9375, bottom: 34.9375, baseline: 27.0625 + frag 0 from TextNode start: 0, length: 1, rect: [773.3125,29.4375 18.6875x34.9375] + "B" + TextNode <#text> + TextNode <#text> + BlockContainer at (8,155.8125) content-size 11.5625x17.46875 floating [BFC] children: inline + line 0 width: 11.5625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [8,155.8125 11.5625x17.46875] + "X" + TextNode <#text> + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-intersection-with-margin.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break.txt similarity index 100% rename from Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-intersection-with-margin.txt rename to Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break.txt diff --git a/Tests/LibWeb/Layout/input/block-and-inline/clear-both-from-inline-formatting-context.html b/Tests/LibWeb/Layout/input/block-and-inline/clear-both-from-inline-formatting-context.html new file mode 100644 index 0000000000..a78f59fb3e --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/clear-both-from-inline-formatting-context.html @@ -0,0 +1,21 @@ + + +
+

A

+

B

+
X
+
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/block-and-inline/float-vertical-intersection-with-margin.html b/Tests/LibWeb/Layout/input/block-and-inline/float-clear-by-line-break.html similarity index 87% rename from Tests/LibWeb/Layout/input/block-and-inline/float-vertical-intersection-with-margin.html rename to Tests/LibWeb/Layout/input/block-and-inline/float-clear-by-line-break.html index 5477d83127..c9eb70f2a1 100644 --- a/Tests/LibWeb/Layout/input/block-and-inline/float-vertical-intersection-with-margin.html +++ b/Tests/LibWeb/Layout/input/block-and-inline/float-clear-by-line-break.html @@ -2,7 +2,6 @@ .a { float: left; width: 100px; - margin-bottom: 4px; } br { diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index b5778078e7..245d051f6f 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -601,7 +601,7 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain } m_margin_state.add_margin(box_state.margin_top); - auto introduce_clearance = clear_floating_boxes(box); + auto introduce_clearance = clear_floating_boxes(box, {}); if (introduce_clearance == DidIntroduceClearance::Yes) m_margin_state.reset(); @@ -752,7 +752,7 @@ CSSPixels BlockFormattingContext::BlockMarginState::current_collapsed_margin() c return collapsed_margin; } -BlockFormattingContext::DidIntroduceClearance BlockFormattingContext::clear_floating_boxes(Node const& child_box) +BlockFormattingContext::DidIntroduceClearance BlockFormattingContext::clear_floating_boxes(Node const& child_box, Optional inline_formatting_context) { auto const& computed_values = child_box.computed_values(); auto result = DidIntroduceClearance::No; @@ -777,7 +777,12 @@ BlockFormattingContext::DidIntroduceClearance BlockFormattingContext::clear_floa for (auto* containing_block = child_box.containing_block(); containing_block && containing_block != &root(); containing_block = containing_block->containing_block()) clearance_y_in_containing_block -= m_state.get(*containing_block).offset.y(); - if (clearance_y_in_containing_block > m_y_offset_of_current_block_container.value()) { + if (inline_formatting_context.has_value()) { + if (clearance_y_in_containing_block > inline_formatting_context->vertical_float_clearance()) { + result = DidIntroduceClearance::Yes; + inline_formatting_context->set_vertical_float_clearance(clearance_y_in_containing_block); + } + } else if (clearance_y_in_containing_block > m_y_offset_of_current_block_container.value()) { result = DidIntroduceClearance::Yes; m_y_offset_of_current_block_container = clearance_y_in_containing_block; } @@ -879,7 +884,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer // First we place the box normally (to get the right y coordinate.) // If we have a LineBuilder, we're in the middle of inline layout, otherwise this is block layout. if (line_builder) { - auto y = line_builder->y_for_float_to_be_inserted_here(box); + auto y = max(line_builder->y_for_float_to_be_inserted_here(box), line_builder->inline_formatting_context().vertical_float_clearance()); box_state.set_content_y(y + box_state.margin_box_top()); } else { place_block_level_element_in_normal_flow_vertically(box, y + box_state.margin_top); diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h index c34639eade..a2014cc56b 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace Web::Layout { @@ -59,7 +60,7 @@ public: No, }; - [[nodiscard]] DidIntroduceClearance clear_floating_boxes(Node const& child_box); + [[nodiscard]] DidIntroduceClearance clear_floating_boxes(Node const& child_box, Optional inline_formatting_context); void reset_margin_state() { m_margin_state.reset(); } diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index 7641524a93..3037f033e7 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -249,7 +249,7 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode) case InlineLevelIterator::Item::Type::ForcedBreak: { line_builder.break_line(LineBuilder::ForcedBreak::Yes); if (item.node) { - auto introduce_clearance = parent().clear_floating_boxes(*item.node); + auto introduce_clearance = parent().clear_floating_boxes(*item.node, *this); if (introduce_clearance == BlockFormattingContext::DidIntroduceClearance::Yes) parent().reset_margin_state(); } @@ -268,8 +268,12 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode) break; case InlineLevelIterator::Item::Type::FloatingElement: - if (is(*item.node)) + if (is(*item.node)) { + auto introduce_clearance = parent().clear_floating_boxes(*item.node, *this); + if (introduce_clearance == BlockFormattingContext::DidIntroduceClearance::Yes) + parent().reset_margin_state(); parent().layout_floating_box(static_cast(*item.node), containing_block(), layout_mode, *m_available_space, 0, &line_builder); + } break; case InlineLevelIterator::Item::Type::Text: { @@ -369,4 +373,14 @@ void InlineFormattingContext::determine_height_of_child(Box const& box, Availabl return parent().determine_height_of_child(box, available_space); } +CSSPixels InlineFormattingContext::vertical_float_clearance() const +{ + return m_vertical_float_clearance; +} + +void InlineFormattingContext::set_vertical_float_clearance(CSSPixels vertical_float_clearance) +{ + m_vertical_float_clearance = vertical_float_clearance; +} + } diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h index c1e5c15a60..5b32e91d74 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h @@ -38,6 +38,9 @@ public: virtual void determine_width_of_child(Box const&, AvailableSpace const&) override; virtual void determine_height_of_child(Box const&, AvailableSpace const&) override; + CSSPixels vertical_float_clearance() const; + void set_vertical_float_clearance(CSSPixels); + private: void generate_line_boxes(LayoutMode); void apply_justification_to_fragments(CSS::TextJustify, LineBox&, bool is_last_line); @@ -48,6 +51,8 @@ private: CSSPixels m_automatic_content_width { 0 }; CSSPixels m_automatic_content_height { 0 }; + + CSSPixels m_vertical_float_clearance { 0 }; }; } diff --git a/Userland/Libraries/LibWeb/Layout/LineBuilder.h b/Userland/Libraries/LibWeb/Layout/LineBuilder.h index fc194872e3..0275d20c95 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBuilder.h +++ b/Userland/Libraries/LibWeb/Layout/LineBuilder.h @@ -49,6 +49,8 @@ public: void recalculate_available_space(); CSSPixels y_for_float_to_be_inserted_here(Box const&); + auto& inline_formatting_context() { return m_context; } + private: void begin_new_line(bool increment_y, bool is_first_break_in_sequence = true);