LibWeb: Apply remaining vertical float clearance to next block level box

Whenever we generate line boxes, we might end up with a residual
vertical float clearance by way of having a `<br>` with `clear: ..` set.
Set the Y offset of the next block level box to place by this vertical
clearance.

Relates to #4058.
This commit is contained in:
Jelle Raaijmakers 2025-03-27 14:59:49 +00:00
parent 8af5f25dd0
commit 9ff3349c0b
6 changed files with 47 additions and 5 deletions

View file

@ -564,6 +564,10 @@ void BlockFormattingContext::layout_inline_children(BlockContainer const& block_
block_container_state.set_content_width(used_width_px);
block_container_state.set_content_height(context.automatic_content_height());
}
// If we end up with remaining vertical clearance, we should make sure the next block is moved down accordingly.
if (context.vertical_float_clearance() > 0)
m_y_offset_of_current_block_container = context.vertical_float_clearance();
}
CSSPixels BlockFormattingContext::compute_auto_height_for_block_level_element(Box const& box, AvailableSpace const& available_space)
@ -704,9 +708,8 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
&& box.computed_values().height().is_auto();
// NOTE: In quirks mode, the html element's height matches the viewport so it can be treated as definite
if (box_state.has_definite_height() || box_is_html_element_in_quirks_mode) {
if (box_state.has_definite_height() || box_is_html_element_in_quirks_mode)
resolve_used_height_if_treated_as_auto(box, available_space);
}
auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, m_layout_mode, box);
@ -817,7 +820,9 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
if (!m_margin_state.box_last_in_flow_child_margin_bottom_collapsed) {
m_margin_state.reset();
}
m_y_offset_of_current_block_container = box_state.offset.y() + box_state.content_height() + box_state.border_box_bottom();
auto box_height = box_state.offset.y() + box_state.content_height() + box_state.border_box_bottom();
if (!m_y_offset_of_current_block_container.has_value() || box_height > m_y_offset_of_current_block_container.value())
m_y_offset_of_current_block_container = box_height;
}
m_margin_state.box_last_in_flow_child_margin_bottom_collapsed = false;

View file

@ -84,9 +84,8 @@ void InlineFormattingContext::run(AvailableSpace const& available_space)
CSSPixels content_height = 0;
for (auto& line_box : m_containing_block_used_values.line_boxes) {
for (auto& line_box : m_containing_block_used_values.line_boxes)
content_height += line_box.height();
}
// NOTE: We ask the parent BFC to calculate the automatic content width of this IFC.
// This ensures that any floated boxes are taken into account.

View file

@ -0,0 +1,23 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x157 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x133 children: not-inline
BlockContainer <div.a> at (8,8) content-size 100x100 floating [BFC] children: not-inline
BlockContainer <(anonymous)> at (8,8) content-size 784x17 children: inline
TextNode <#text>
BreakNode <br.b>
TextNode <#text>
BlockContainer <p> at (8,124) content-size 784x17 children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,124 27.15625x17] baseline: 13.296875
"foo"
TextNode <#text>
BlockContainer <(anonymous)> at (8,157) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x157]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x133]
PaintableWithLines (BlockContainer<DIV>.a) [8,8 100x100]
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x17]
PaintableWithLines (BlockContainer<P>) [8,124 784x17]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,157 784x0]

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<style>
.a {
background: green;
float: left;
height: 100px;
width: 100px;
}
.b {
clear: both;
}
</style>
<div class="a"></div>
<br class="b">
<p>foo</p>