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();
}