diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/margin-must-not-collapse-across-nested-bfc.txt b/Tests/LibWeb/Layout/expected/block-and-inline/margin-must-not-collapse-across-nested-bfc.txt new file mode 100644 index 0000000000..556eb93764 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/margin-must-not-collapse-across-nested-bfc.txt @@ -0,0 +1,6 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x116 [BFC] children: not-inline + BlockContainer at (8,30) content-size 784x100 children: not-inline + BlockContainer at (8,30) content-size 784x20 children: not-inline + BlockContainer at (8,80) content-size 784x0 [BFC] children: not-inline + BlockContainer at (8,110) content-size 784x20 children: not-inline diff --git a/Tests/LibWeb/Layout/expected/table/basic.txt b/Tests/LibWeb/Layout/expected/table/basic.txt index 8d3019c1ab..ceca965598 100644 --- a/Tests/LibWeb/Layout/expected/table/basic.txt +++ b/Tests/LibWeb/Layout/expected/table/basic.txt @@ -1,8 +1,8 @@ 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 784x58.40625 children: not-inline - TableWrapper <(anonymous)> at (8,8) content-size 784x0 [BFC] children: not-inline - TableBox at (8,8) content-size 784x0 [TFC] children: not-inline + TableWrapper <(anonymous)> at (8,8) content-size 0x0 [BFC] children: not-inline + TableBox at (8,8) content-size 0x0 [TFC] children: not-inline BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline TextNode <#text> TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/block-and-inline/margin-must-not-collapse-across-nested-bfc.html b/Tests/LibWeb/Layout/input/block-and-inline/margin-must-not-collapse-across-nested-bfc.html new file mode 100644 index 0000000000..0e611a64c5 --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/margin-must-not-collapse-across-nested-bfc.html @@ -0,0 +1,20 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 07159f8964..40ff7b255e 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -552,13 +552,23 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain m_margin_state.reset(); } - m_margin_state.add_margin(box_state.margin_top); - m_margin_state.update_block_waiting_for_final_y_position(); + CSSPixels margin_top = 0; + auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, box); - auto margin_top = m_margin_state.current_collapsed_margin(); - if (m_margin_state.has_block_container_waiting_for_final_y_position()) { - // If first child margin top will collapse with margin-top of containing block then margin-top of child is 0 - margin_top = 0; + if (independent_formatting_context) { + // Margins of elements that establish new formatting contexts do not collapse with their in-flow children + m_margin_state.reset(); + + margin_top = box_state.margin_top; + } else { + m_margin_state.add_margin(box_state.margin_top); + m_margin_state.update_block_waiting_for_final_y_position(); + + margin_top = m_margin_state.current_collapsed_margin(); + if (m_margin_state.has_block_container_waiting_for_final_y_position()) { + // If first child margin top will collapse with margin-top of containing block then margin-top of child is 0 + margin_top = 0; + } } place_block_level_element_in_normal_flow_vertically(box, y + margin_top); @@ -567,36 +577,31 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain place_block_level_element_in_normal_flow_horizontally(box, available_space); - OwnPtr independent_formatting_context; - if (!box.is_replaced_box() && box.has_children()) { - independent_formatting_context = create_independent_formatting_context_if_needed(m_state, box); - if (independent_formatting_context) { - // Margins of elements that establish new formatting contexts do not collapse with their in-flow children - m_margin_state.reset(); - - independent_formatting_context->run(box, layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); + if (independent_formatting_context) { + // This box establishes a new formatting context. Pass control to it. + independent_formatting_context->run(box, layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); + } else { + // This box participates in the current block container's flow. + if (box.children_are_inline()) { + layout_inline_children(verify_cast(box), layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); } else { - if (box.children_are_inline()) { - layout_inline_children(verify_cast(box), layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); - } else { - if (box_state.border_top > 0 || box_state.padding_top > 0) { - // margin-top of block container can't collapse with it's children if it has non zero border or padding - m_margin_state.reset(); - } 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 - 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()); - }); - } - - layout_block_level_children(verify_cast(box), layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); + if (box_state.border_top > 0 || box_state.padding_top > 0) { + // margin-top of block container can't collapse with it's children if it has non zero border or padding + m_margin_state.reset(); + } 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 + 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()); + }); } + + layout_block_level_children(verify_cast(box), layout_mode, box_state.available_inner_space_or_constraints_from(available_space)); } } compute_height(box, available_space); - if (!margins_collapse_through(box, m_state)) { + if (independent_formatting_context || !margins_collapse_through(box, m_state)) { if (!m_margin_state.box_last_in_flow_child_margin_bottom_collapsed) { m_margin_state.reset(); }