diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index c9a1cfe55f1..01d9b1efc6d 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -431,6 +431,7 @@ fn compute_inline_content_sizes_for_block_level_boxes( containing_block, &LogicalVec2::zero(), false, /* auto_block_size_stretches_to_containing_block */ + false, /* is_replaced */ false, /* is_table */ !matches!(base.style.pseudo(), Some(PseudoElement::ServoAnonymousBox)), |_| None, /* TODO: support preferred aspect ratios on non-replaced boxes */ diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 21383ca40b2..d04c69f939f 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -215,6 +215,7 @@ impl IndependentFormattingContext { containing_block, auto_minimum, auto_block_size_stretches_to_containing_block, + self.is_replaced(), is_table, true, /* establishes_containing_block */ |padding_border_sums| self.preferred_aspect_ratio(padding_border_sums), diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index c745081e862..46eda7ccbde 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -10,6 +10,7 @@ use std::ops::{Add, AddAssign}; use app_units::Au; use serde::Serialize; use style::properties::ComputedValues; +use style::values::computed::LengthPercentage; use style::Zero; use crate::context::LayoutContext; @@ -115,6 +116,7 @@ pub(crate) fn outer_inline( containing_block: &IndefiniteContainingBlock, auto_minimum: &LogicalVec2, auto_block_size_stretches_to_containing_block: bool, + is_replaced: bool, is_table: bool, establishes_containing_block: bool, get_preferred_aspect_ratio: impl FnOnce(&LogicalVec2) -> Option, @@ -187,7 +189,7 @@ pub(crate) fn outer_inline( ), }) }; - let (preferred_min_content, preferred_max_content, preferred_depends_on_block_constraints) = + let (mut preferred_min_content, preferred_max_content, preferred_depends_on_block_constraints) = resolve_non_initial(content_box_sizes.inline.preferred) .unwrap_or_else(|| resolve_non_initial(Size::FitContent).unwrap()); let (mut min_min_content, mut min_max_content, mut min_depends_on_block_constraints) = @@ -196,7 +198,7 @@ pub(crate) fn outer_inline( auto_minimum.inline, false, )); - let (max_min_content, max_max_content, max_depends_on_block_constraints) = + let (mut max_min_content, max_max_content, max_depends_on_block_constraints) = resolve_non_initial(content_box_sizes.inline.max) .map(|(min_content, max_content, depends_on_block_constraints)| { ( @@ -207,6 +209,30 @@ pub(crate) fn outer_inline( }) .unwrap_or_default(); + // https://drafts.csswg.org/css-sizing-3/#replaced-percentage-min-contribution + // > If the box is replaced, a cyclic percentage in the value of any max size property + // > or preferred size property (width/max-width/height/max-height), is resolved against + // > zero when calculating the min-content contribution in the corresponding axis. + // + // This means that e.g. the min-content contribution of `width: calc(100% + 100px)` + // should be 100px, but it's just zero on other browsers, so we do the same. + if is_replaced { + let has_percentage = |size: Size| { + // We need a comment here to avoid breaking `./mach test-tidy`. + matches!(size, Size::Numeric(numeric) if numeric.has_percentage()) + }; + if content_box_sizes.inline.preferred.is_initial() && + has_percentage(style.box_size(containing_block.writing_mode).inline) + { + preferred_min_content = Au::zero(); + } + if content_box_sizes.inline.max.is_initial() && + has_percentage(style.max_box_size(containing_block.writing_mode).inline) + { + max_min_content = Some(Au::zero()); + } + } + // Regardless of their sizing properties, tables are always forced to be at least // as big as their min-content size, so floor the minimums. if is_table { diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index d97e68cb65e..d248c65d75b 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -581052,6 +581052,13 @@ {} ] ], + "intrinsic-percent-replaced-028.html": [ + "f54245a1e1f0aabff40ed8823279b8c0bb48f93d", + [ + null, + {} + ] + ], "intrinsic-size-fallback-replaced.html": [ "a3325b0aea01c008ec322a20e0f279d5bd765b1c", [ diff --git a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-abspos.html.ini b/tests/wpt/meta/css/css-sizing/keyword-sizes-on-abspos.html.ini deleted file mode 100644 index 508b6bddd70..00000000000 --- a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-abspos.html.ini +++ /dev/null @@ -1,9 +0,0 @@ -[keyword-sizes-on-abspos.html] - [.test 17] - expected: FAIL - - [.test 22] - expected: FAIL - - [.test 27] - expected: FAIL diff --git a/tests/wpt/tests/css/css-sizing/intrinsic-percent-replaced-028.html b/tests/wpt/tests/css/css-sizing/intrinsic-percent-replaced-028.html new file mode 100644 index 00000000000..f54245a1e1f --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/intrinsic-percent-replaced-028.html @@ -0,0 +1,50 @@ + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ + +
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + +