From 1966ab182fcac6fbbdc4b8ed95c93023e71f87c2 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Thu, 27 Feb 2025 14:54:44 +0100 Subject: [PATCH] layout: Use definite cross size to compute flex base size (#35688) An intrinsic flex base size depends on the contents, which may depend on the cross size through an aspect ratio. We were only taking this into account if the preferred cross size was numeric, but `auto` or `stretch` can also be definite. Signed-off-by: Oriol Brufau --- components/layout_2020/flexbox/layout.rs | 48 ++++++----- tests/wpt/meta/MANIFEST.json | 7 ++ .../intrinsic-percent-replaced-026.html.ini | 2 - .../tests/css/css-flexbox/flex-basis-013.html | 80 +++++++++++++++++++ 4 files changed, 110 insertions(+), 27 deletions(-) delete mode 100644 tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-026.html.ini create mode 100644 tests/wpt/tests/css/css-flexbox/flex-basis-013.html diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index d36a230ca56..4546a90346c 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -2673,37 +2673,40 @@ impl FlexItemBox { let content_size = LazyCell::new(|| { let flex_item = &self.independent_formatting_context; - - // > B: If the flex item has ... - // > - a preferred aspect ratio, - // > - a used flex basis of content, and - // > - a definite cross size, - // > then the flex base size is calculated from its used cross size and the flex item’s aspect ratio. let main_axis = if cross_axis_is_item_block_axis { Direction::Inline } else { Direction::Block }; + // > If a single-line flex container has a definite cross size, the automatic preferred // > outer cross size of any stretched flex items is the flex container’s inner cross size // > (clamped to the flex item’s min and max cross size) and is considered definite. let cross_stretch_size = container_definite_inner_size .cross .map(|v| v - pbm_auto_is_zero.cross); - let cross_size = if content_box_size.cross.is_initial() && - item_with_auto_cross_size_stretches_to_container_size + let cross_size = SizeConstraint::new( + if content_box_size.cross.is_initial() && + item_with_auto_cross_size_stretches_to_container_size + { + cross_stretch_size + } else { + content_box_size + .cross + .maybe_resolve_extrinsic(cross_stretch_size) + }, + content_min_box_size.cross, + content_max_box_size.cross, + ); + + // > B: If the flex item has ... + // > - a preferred aspect ratio, + // > - a used flex basis of content, and + // > - a definite cross size, + // > then the flex base size is calculated from its used cross size and the flex item’s aspect ratio. + if let (Some(ratio), SizeConstraint::Definite(cross_size)) = + (preferred_aspect_ratio, cross_size) { - cross_stretch_size - } else { - content_box_size - .cross - .maybe_resolve_extrinsic(cross_stretch_size) - }; - if let (Some(ratio), Some(cross_size)) = (preferred_aspect_ratio, cross_size) { - let cross_size = cross_size.clamp_between_extremums( - content_min_box_size.cross, - content_max_box_size.cross, - ); return ratio.compute_dependent_size(main_axis, cross_size).into(); } @@ -2721,12 +2724,7 @@ impl FlexItemBox { // The main axis is the inline axis, so we can get the content size from the normal // preferred widths calculation. let constraint_space = ConstraintSpace::new( - SizeConstraint::new( - // TODO(#32853): handle size keywords. - content_box_size.cross.to_numeric(), - content_min_box_size.cross, - content_max_box_size.cross, - ), + cross_size, flex_item.style().writing_mode, preferred_aspect_ratio, ); diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index db9659582a4..c9724e7a2a1 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -576237,6 +576237,13 @@ {} ] ], + "flex-basis-013.html": [ + "c11624a47eb07f9b46affbb735cb707c6aec600d", + [ + null, + {} + ] + ], "flex-basis-intrinsics-001.html": [ "164abd82e5fb6c2dd140347287613888f23b2599", [ diff --git a/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-026.html.ini b/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-026.html.ini deleted file mode 100644 index 9073aa603c4..00000000000 --- a/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-026.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[intrinsic-percent-replaced-026.html] - expected: FAIL diff --git a/tests/wpt/tests/css/css-flexbox/flex-basis-013.html b/tests/wpt/tests/css/css-flexbox/flex-basis-013.html new file mode 100644 index 00000000000..c11624a47eb --- /dev/null +++ b/tests/wpt/tests/css/css-flexbox/flex-basis-013.html @@ -0,0 +1,80 @@ + + +CSS Test: flex base size that depends on cross size + + + + + + + + +
+
+ + + + +