Respect min/max constraints in the block axis of block containers (#33203)

Consider a block container that establishes an inline formatting context
and has a definite `block-size` which is clamped by `min-block-size` or
`max-block-size`.

We were already sizing such container correctly, however, its contents
were resolving their percentages against the unclamped `block-size`
value.

This patch fixes the `ContainingBlock` that we pass to the contents so
that they resolve percentages correctly.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Oriol Brufau 2024-08-27 11:05:43 +02:00 committed by GitHub
parent fef44620cc
commit 5d43d88b6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 19 deletions

View file

@ -127,7 +127,7 @@ use crate::fragment_tree::{
use crate::geom::{LogicalRect, LogicalVec2, PhysicalRect, ToLogical};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::sizing::ContentSizes;
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
use crate::ContainingBlock;
// From gfxFontConstants.h in Firefox.
@ -1945,14 +1945,17 @@ impl IndependentFormattingContext {
IndependentFormattingContext::NonReplaced(non_replaced) => {
let box_size = non_replaced
.style
.content_box_size(layout.containing_block, &pbm);
.content_box_size(layout.containing_block, &pbm)
.map(|v| v.map(Au::from));
let max_box_size = non_replaced
.style
.content_max_box_size(layout.containing_block, &pbm);
.content_max_box_size(layout.containing_block, &pbm)
.map(|v| v.map(Au::from));
let min_box_size = non_replaced
.style
.content_min_box_size(layout.containing_block, &pbm)
.auto_is(Length::zero);
.map(|v| v.map(Au::from))
.auto_is(Au::zero);
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
let tentative_inline_size = box_size.inline.auto_is(|| {
@ -1969,10 +1972,13 @@ impl IndependentFormattingContext {
// always results in that size.
let inline_size = tentative_inline_size
.clamp_between_extremums(min_box_size.inline, max_box_size.inline);
let block_size = box_size
.block
.map(|v| v.clamp_between_extremums(min_box_size.block, max_box_size.block));
let containing_block_for_children = ContainingBlock {
inline_size: inline_size.into(),
block_size: box_size.block.map(|t| t.into()),
inline_size,
block_size,
style: &non_replaced.style,
};
assert_eq!(
@ -2001,17 +2007,15 @@ impl IndependentFormattingContext {
Some(inline) => (inline, independent_layout.content_block_size),
None => {
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
let tentative_block_size = box_size
.block
.auto_is(|| independent_layout.content_block_size.into());
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
// In this case “applying the rules above again” with a non-auto block-size
// always results in that size.
let block_size = tentative_block_size
.clamp_between_extremums(min_box_size.block, max_box_size.block);
(inline_size.into(), block_size.into())
let block_size = block_size.auto_is(|| {
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
// In this case “applying the rules above again” with a non-auto block-size
// always results in that size.
independent_layout
.content_block_size
.clamp_between_extremums(min_box_size.block, max_box_size.block)
});
(inline_size, block_size)
},
};

View file

@ -81619,6 +81619,19 @@
{}
]
],
"max-height-applies-to-017.html": [
"3543b19ee33dbbd93e3b8455458123bf298bd4a1",
[
null,
[
[
"/css/CSS2/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"max-height-percentage-001.xht": [
"5ac6f609e9c68384771a207119363215ad8149ca",
[

View file

@ -1,2 +0,0 @@
[max-height-applies-to-014.xht]
expected: FAIL

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<title>CSS Test: Max-Height applied to element with 'display' set to 'inline-block'</title>
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-heights">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="The percentage in #child should resolve against the 100px maximum of #parent, not against 200px.">
<style>
#parent {
display: inline-block;
height: 200px;
max-height: 100px;
background: red;
}
#child {
display: inline-block;
width: 100px;
height: 100%;
background: green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="parent">
<span id="child"></span>
</div>