mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:37:35 +00:00
LibWeb: Reset margin collapsing state only if box indeed add clearance
This fixes the issue when margin collapsing state was always reset if a box has clear property not equal to none even if it does not actually introduce clearance.
This commit is contained in:
parent
b0a43404b9
commit
7cc20f4cb5
6 changed files with 83 additions and 13 deletions
|
@ -0,0 +1,7 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x110 children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 784x110 children: not-inline
|
||||||
|
BlockContainer <div.square.white> at (8,8) content-size 100x100 floating [BFC] children: not-inline
|
||||||
|
BlockContainer <div.clearfix> at (8,108) content-size 10x10 children: not-inline
|
||||||
|
BlockContainer <div.square.black> at (8,218) content-size 49x49 floating [BFC] children: not-inline
|
|
@ -0,0 +1,14 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x125.9375 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x109.9375 children: not-inline
|
||||||
|
BlockContainer <div.upper> at (8,8) content-size 784x17.46875 children: inline
|
||||||
|
line 0 width: 46.15625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 5, rect: [8,8 46.15625x17.46875]
|
||||||
|
"upper"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.mystery> at (8,100.46875) content-size 784x0 children: not-inline
|
||||||
|
BlockContainer <div.lower> at (8,100.46875) content-size 784x17.46875 children: inline
|
||||||
|
line 0 width: 43.359375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 5, rect: [8,100.46875 43.359375x17.46875]
|
||||||
|
"lower"
|
||||||
|
TextNode <#text>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<style>
|
||||||
|
.clearfix {
|
||||||
|
clear: both;
|
||||||
|
margin-top: 9999px;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
background-color: black;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
.square {
|
||||||
|
float: left;
|
||||||
|
width: 49px;
|
||||||
|
height: 49px;
|
||||||
|
}
|
||||||
|
.white {
|
||||||
|
background-color: salmon;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.black {
|
||||||
|
background-color: slateblue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div><div class="square white"></div><div class="clearfix"></div><div class="square black"></div></div>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!doctype html><style>
|
||||||
|
.upper {
|
||||||
|
margin-bottom: 75px;
|
||||||
|
}
|
||||||
|
.mystery {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
</style><body><div class="upper">upper</div><div class="mystery"></div><div class="lower">lower
|
|
@ -536,26 +536,27 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
|
||||||
|
|
||||||
resolve_vertical_box_model_metrics(box, m_state);
|
resolve_vertical_box_model_metrics(box, m_state);
|
||||||
|
|
||||||
auto const y = m_y_offset_of_current_block_container.value();
|
|
||||||
|
|
||||||
if (box.is_floating()) {
|
if (box.is_floating()) {
|
||||||
|
auto const y = m_y_offset_of_current_block_container.value();
|
||||||
auto margin_top = !m_margin_state.has_block_container_waiting_for_final_y_position() ? m_margin_state.current_collapsed_margin() : 0;
|
auto margin_top = !m_margin_state.has_block_container_waiting_for_final_y_position() ? m_margin_state.current_collapsed_margin() : 0;
|
||||||
layout_floating_box(box, block_container, layout_mode, available_space, margin_top + y);
|
layout_floating_box(box, block_container, layout_mode, available_space, margin_top + y);
|
||||||
bottom_of_lowest_margin_box = max(bottom_of_lowest_margin_box, box_state.offset.y() + box_state.content_height() + box_state.margin_box_bottom());
|
bottom_of_lowest_margin_box = max(bottom_of_lowest_margin_box, box_state.offset.y() + box_state.content_height() + box_state.margin_box_bottom());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_margin_state.add_margin(box_state.margin_top);
|
||||||
|
auto introduce_clearance = clear_floating_boxes(box);
|
||||||
|
if (introduce_clearance == DidIntroduceClearance::Yes)
|
||||||
|
m_margin_state.reset();
|
||||||
|
|
||||||
|
auto const y = m_y_offset_of_current_block_container.value();
|
||||||
|
|
||||||
if (box_state.has_definite_height()) {
|
if (box_state.has_definite_height()) {
|
||||||
compute_height(box, available_space);
|
compute_height(box, available_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (box.computed_values().clear() != CSS::Clear::None) {
|
|
||||||
m_margin_state.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, box);
|
auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, box);
|
||||||
|
|
||||||
m_margin_state.add_margin(box_state.margin_top);
|
|
||||||
m_margin_state.update_block_waiting_for_final_y_position();
|
m_margin_state.update_block_waiting_for_final_y_position();
|
||||||
CSSPixels margin_top = m_margin_state.current_collapsed_margin();
|
CSSPixels margin_top = m_margin_state.current_collapsed_margin();
|
||||||
|
|
||||||
|
@ -592,7 +593,9 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
|
||||||
} else if (!m_margin_state.has_block_container_waiting_for_final_y_position()) {
|
} else if (!m_margin_state.has_block_container_waiting_for_final_y_position()) {
|
||||||
// margin-top of block container can be updated during children layout hence it's final y position yet to be determined
|
// margin-top of block container can be updated during children layout hence it's final y position yet to be determined
|
||||||
m_margin_state.register_block_container_y_position_update_callback([&](CSSPixels margin_top) {
|
m_margin_state.register_block_container_y_position_update_callback([&](CSSPixels margin_top) {
|
||||||
place_block_level_element_in_normal_flow_vertically(box, margin_top + y + box_state.border_box_top());
|
if (introduce_clearance == DidIntroduceClearance::No) {
|
||||||
|
place_block_level_element_in_normal_flow_vertically(box, margin_top + y);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,10 +692,10 @@ CSSPixels BlockFormattingContext::BlockMarginState::current_collapsed_margin() c
|
||||||
return collapsed_margin;
|
return collapsed_margin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically(Box const& child_box, CSSPixels y)
|
BlockFormattingContext::DidIntroduceClearance BlockFormattingContext::clear_floating_boxes(Box const& child_box)
|
||||||
{
|
{
|
||||||
auto& box_state = m_state.get_mutable(child_box);
|
|
||||||
auto const& computed_values = child_box.computed_values();
|
auto const& computed_values = child_box.computed_values();
|
||||||
|
auto result = DidIntroduceClearance::No;
|
||||||
|
|
||||||
auto clear_floating_boxes = [&](FloatSideData& float_side) {
|
auto clear_floating_boxes = [&](FloatSideData& float_side) {
|
||||||
if (!float_side.current_boxes.is_empty()) {
|
if (!float_side.current_boxes.is_empty()) {
|
||||||
|
@ -714,9 +717,11 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically
|
||||||
for (auto* containing_block = child_box.containing_block(); containing_block && containing_block != &root(); containing_block = containing_block->containing_block())
|
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();
|
clearance_y_in_containing_block -= m_state.get(*containing_block).offset.y();
|
||||||
|
|
||||||
if (clearance_y_in_containing_block > y)
|
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;
|
m_y_offset_of_current_block_container = clearance_y_in_containing_block;
|
||||||
y = max(y, clearance_y_in_containing_block);
|
}
|
||||||
|
|
||||||
float_side.clear();
|
float_side.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -727,8 +732,13 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically
|
||||||
if ((computed_values.clear() == CSS::Clear::Right || computed_values.clear() == CSS::Clear::Both) && !child_box.is_flex_item())
|
if ((computed_values.clear() == CSS::Clear::Right || computed_values.clear() == CSS::Clear::Both) && !child_box.is_flex_item())
|
||||||
clear_floating_boxes(m_right_floats);
|
clear_floating_boxes(m_right_floats);
|
||||||
|
|
||||||
y += box_state.border_box_top();
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically(Box const& child_box, CSSPixels y)
|
||||||
|
{
|
||||||
|
auto& box_state = m_state.get_mutable(child_box);
|
||||||
|
y += box_state.border_box_top();
|
||||||
box_state.set_content_offset(CSSPixelPoint { box_state.offset.x(), y.value() });
|
box_state.set_content_offset(CSSPixelPoint { box_state.offset.x(), y.value() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,13 @@ private:
|
||||||
|
|
||||||
void layout_list_item_marker(ListItemBox const&);
|
void layout_list_item_marker(ListItemBox const&);
|
||||||
|
|
||||||
|
enum class DidIntroduceClearance {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] DidIntroduceClearance clear_floating_boxes(Box const& child_box);
|
||||||
|
|
||||||
enum class FloatSide {
|
enum class FloatSide {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue