From 64fe52e918456fa5275634caf1b9d81d560609c9 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Sat, 12 Apr 2025 07:22:37 -0700 Subject: [PATCH] layout: Enforce min-content min main size of flex-level tables (#36469) Additionally to the minimum specified in min-width or min-height, tables also enforce a `min-content` minimum. This was handled in `Sizes::resolve()`, but flex items don't use that. So this patch moves the logic into `Size::resolve_for_min()`. Testing: Covered by WPT Signed-off-by: Oriol Brufau --- components/layout_2020/flexbox/layout.rs | 14 +++++--- components/layout_2020/geom.rs | 33 ++++++++++++------- .../table-as-item-fixed-min-width-3.html.ini | 2 -- ...em-min-content-height-1.tentative.html.ini | 2 -- ...em-min-content-height-2.tentative.html.ini | 2 -- 5 files changed, 31 insertions(+), 22 deletions(-) delete mode 100644 tests/wpt/meta/css/css-flexbox/table-as-item-fixed-min-width-3.html.ini delete mode 100644 tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-1.tentative.html.ini delete mode 100644 tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-2.tentative.html.ini diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index c43ab84fc54..34904ae1053 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -2155,10 +2155,7 @@ impl FlexItem<'_> { #[inline] fn is_table(&self) -> bool { - match &self.box_.independent_formatting_context.contents { - IndependentFormattingContextContents::NonReplaced(content) => content.is_table(), - IndependentFormattingContextContents::Replaced(_) => false, - } + self.box_.is_table() } } @@ -2366,6 +2363,7 @@ impl FlexItemBox { get_automatic_minimum_size, stretch_size.main, &main_content_sizes, + self.is_table(), ); FlexItem { @@ -2724,4 +2722,12 @@ impl FlexItemBox { }, } } + + #[inline] + fn is_table(&self) -> bool { + match &self.independent_formatting_context.contents { + IndependentFormattingContextContents::NonReplaced(content) => content.is_table(), + IndependentFormattingContextContents::Replaced(_) => false, + } + } } diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 56da1c5d7f5..638dfae04ea 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -880,8 +880,9 @@ impl Size { get_automatic_minimum_size: impl FnOnce() -> Au, stretch_size: Option, content_size: &LazyCell, + is_table: bool, ) -> Au { - match self { + let result = match self { Self::Initial => get_automatic_minimum_size(), Self::MinContent => content_size.min_content, Self::MaxContent => content_size.max_content, @@ -889,6 +890,19 @@ impl Size { Self::FitContent => content_size.shrink_to_fit(stretch_size.unwrap_or_default()), Self::Stretch => stretch_size.unwrap_or_default(), Self::Numeric(numeric) => *numeric, + }; + if is_table { + // In addition to the specified minimum, the inline size of a table is forced to be + // at least as big as its min-content size. + // + // Note that if there are collapsed columns, only the inline size of the table grid will + // shrink, while the size of the table wrapper (being computed here) won't be affected. + // However, collapsed rows should typically affect the block size of the table wrapper, + // so it might be wrong to use this function for that case. + // This is being discussed in https://github.com/w3c/csswg-drafts/issues/11408 + result.max(content_size.min_content) + } else { + result } } @@ -1027,17 +1041,12 @@ impl Sizes { let preferred = self.preferred .resolve_for_preferred(automatic_size, stretch_size, &content_size); - let mut min = - self.min - .resolve_for_min(get_automatic_minimum_size, stretch_size, &content_size); - if is_table { - // In addition to the specified minimum, the inline size of a table is forced to be - // at least as big as its min-content size. - // Note that if there are collapsed columns, only the inline size of the table grid will - // shrink, while the size of the table wrapper (being computed here) won't be affected. - // This is being discussed in https://github.com/w3c/csswg-drafts/issues/11408 - min.max_assign(content_size.min_content); - } + let min = self.min.resolve_for_min( + get_automatic_minimum_size, + stretch_size, + &content_size, + is_table, + ); let max = self.max.resolve_for_max(stretch_size, &content_size); preferred.clamp_between_extremums(min, max) } diff --git a/tests/wpt/meta/css/css-flexbox/table-as-item-fixed-min-width-3.html.ini b/tests/wpt/meta/css/css-flexbox/table-as-item-fixed-min-width-3.html.ini deleted file mode 100644 index d216a20f66b..00000000000 --- a/tests/wpt/meta/css/css-flexbox/table-as-item-fixed-min-width-3.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-as-item-fixed-min-width-3.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-1.tentative.html.ini b/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-1.tentative.html.ini deleted file mode 100644 index 17d5171d154..00000000000 --- a/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-1.tentative.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-as-item-min-content-height-1.tentative.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-2.tentative.html.ini b/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-2.tentative.html.ini deleted file mode 100644 index b31200fbdb9..00000000000 --- a/tests/wpt/meta/css/css-flexbox/table-as-item-min-content-height-2.tentative.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-as-item-min-content-height-2.tentative.html] - expected: FAIL