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 @@
+
+
+
\ 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);