From b8c04b4bad1636f78cddf8ec1944386520600da0 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Thu, 27 Jul 2023 16:37:21 +0200 Subject: [PATCH] Floor child sizes in calculate_inline_content_size_for_block_level_boxes (#30034) Calculating the max-content size of a block container may add the outer max-content sizes of multiple children. The problem is that the outer size may be negative (due to margins), producing an incorrect result. In particular, it could happen that the max-content size was 50-25=25, but the min-content size would just take the maximum and be 50, which doesn't make sense. Therefore, this patch floors the size of all children by 0. This seems to match Blink. Firefox and WebKit don't floor in some cases, but then the result seems suboptimal to me. Note that there is no spec for this, see https://github.com/w3c/csswg-drafts/issues/9120 for details. --- components/layout_2020/flow/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 98a62302264..577070fbdab 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -250,7 +250,8 @@ fn calculate_inline_content_size_for_block_level_boxes( BlockLevelBox::OutOfFlowFloatBox(ref mut float_box) => { let size = float_box .contents - .outer_inline_content_sizes(layout_context, writing_mode); + .outer_inline_content_sizes(layout_context, writing_mode) + .max(ContentSizes::zero()); let style_box = &float_box.contents.style().get_box(); Some((size, style_box.float, style_box.clear)) }, @@ -259,14 +260,17 @@ fn calculate_inline_content_size_for_block_level_boxes( } => { let size = sizing::outer_inline(&style, writing_mode, || { contents.inline_content_sizes(layout_context, style.writing_mode) - }); + }) + .max(ContentSizes::zero()); // A block in the same BFC can overlap floats, it's not moved next to them, // so we shouldn't add its size to the size of the floats. // Instead, we treat it like an independent block with 'clear: both'. Some((size, Float::None, Clear::Both)) }, BlockLevelBox::Independent(ref mut independent) => { - let size = independent.outer_inline_content_sizes(layout_context, writing_mode); + let size = independent + .outer_inline_content_sizes(layout_context, writing_mode) + .max(ContentSizes::zero()); Some((size, Float::None, independent.style().get_box().clear)) }, }