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.
This commit is contained in:
Oriol Brufau 2023-07-27 16:37:21 +02:00 committed by GitHub
parent 77c6a61dfa
commit b8c04b4bad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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))
},
}