LibWeb: Do not clear float sides for floating boxes with clear: ..

We used to always clear the side data after encountering a box with
`clear: ..`, but this is not the right thing to do if that same box also
has `float: ..` set. For example, with `clear: right` and `float: left`
it might be that the next box still wants to clear the right side, and
since the previous box is floating it did not push the next box down far
enough to justify clearing the side data at that point.

This changes the logic to only clear the float side if the clearing box
itself is not floating. We also no longer clear the opposite side after
placing a floating box; that doesn't seem to be necessary anymore.

Fixes #4102.
This commit is contained in:
Jelle Raaijmakers
2025-03-26 19:26:20 +00:00
parent a6b664d4d0
commit f340f8682b
Notes: github-actions[bot] 2025-03-27 00:57:50 +00:00
4 changed files with 57 additions and 14 deletions

View File

@@ -933,7 +933,8 @@ BlockFormattingContext::DidIntroduceClearance BlockFormattingContext::clear_floa
m_y_offset_of_current_block_container = clearance_y_in_containing_block;
}
float_side.clear();
if (!child_box.is_floating())
float_side.clear();
}
};
@@ -1053,7 +1054,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
}
// Then we float it to the left or right.
auto float_box = [&](FloatSide side, FloatSideData& side_data, FloatSideData& other_side_data) {
auto float_box = [&](FloatSide side, FloatSideData& side_data) {
CSSPixels offset_from_edge = 0;
auto float_to_edge = [&] {
if (side == FloatSide::Left)
@@ -1165,18 +1166,13 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
// NOTE: We don't set the X position here, that happens later, once we know the root block width.
// See parent_context_did_dimension_child_root_box() for that logic.
box_state.set_content_y(y);
// If the new box was inserted below the bottom of the opposite side,
// we reset the other side back to its edge.
if (top_margin_edge > other_side_data.y_offset)
other_side_data.clear();
};
// Next, float to the left and/or right
if (box.computed_values().float_() == CSS::Float::Left) {
float_box(FloatSide::Left, m_left_floats, m_right_floats);
float_box(FloatSide::Left, m_left_floats);
} else if (box.computed_values().float_() == CSS::Float::Right) {
float_box(FloatSide::Right, m_right_floats, m_left_floats);
float_box(FloatSide::Right, m_right_floats);
}
m_state.get_mutable(root()).add_floating_descendant(box);