layout: Respect alignment when sizing replaced abspos (#35085)

If an absolutely position element which is replaced has `justify-self`
or `align-self` set to `stretch`, and no inset is `auto` on that axis,
then an automatic size should behave as `stretch`, not as `fit-content`.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-01-20 05:25:00 -08:00 committed by GitHub
parent 2965b2fda7
commit f6c166533e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 92 additions and 69 deletions

View file

@ -1972,18 +1972,21 @@ impl FlexItem<'_> {
containing_block, containing_block,
item_style, item_style,
self.preferred_aspect_ratio, self.preferred_aspect_ratio,
&Sizes::new( LogicalVec2 {
block: &Sizes::new(
block_size block_size
.to_definite() .to_definite()
.map_or(Size::Initial, Size::Numeric), .map_or(Size::Initial, Size::Numeric),
Size::Numeric(min_size.block), Size::Numeric(min_size.block),
max_size.block.map_or(Size::Initial, Size::Numeric), max_size.block.map_or(Size::Initial, Size::Numeric),
), ),
&Sizes::new( inline: &Sizes::new(
Size::Numeric(inline_size), Size::Numeric(inline_size),
Size::Numeric(min_size.inline), Size::Numeric(min_size.inline),
max_size.inline.map_or(Size::Initial, Size::Numeric), max_size.inline.map_or(Size::Initial, Size::Numeric),
), ),
},
Size::FitContent.into(),
flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero), flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero),
); );
let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross; let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross;
@ -2792,7 +2795,8 @@ impl FlexItemBox {
flex_context.containing_block, flex_context.containing_block,
style, style,
preferred_aspect_ratio, preferred_aspect_ratio,
&Sizes::new( LogicalVec2 {
block: &Sizes::new(
content_box_size content_box_size
.block .block
.non_auto() .non_auto()
@ -2800,7 +2804,7 @@ impl FlexItemBox {
Size::Numeric(min_size.block), Size::Numeric(min_size.block),
max_size.block.map_or(Size::Initial, Size::Numeric), max_size.block.map_or(Size::Initial, Size::Numeric),
), ),
&Sizes::new( inline: &Sizes::new(
content_box_size content_box_size
.inline .inline
.non_auto() .non_auto()
@ -2808,6 +2812,8 @@ impl FlexItemBox {
Size::Numeric(min_size.inline), Size::Numeric(min_size.inline),
max_size.inline.map_or(Size::Initial, Size::Numeric), max_size.inline.map_or(Size::Initial, Size::Numeric),
), ),
},
Size::FitContent.into(),
padding_border_margin.padding_border_sums + padding_border_margin.padding_border_sums +
padding_border_margin.margin.auto_is(Au::zero).sum(), padding_border_margin.margin.auto_is(Au::zero).sum(),
) )

View file

@ -68,7 +68,23 @@ impl<T: Default> Default for LogicalVec2<T> {
} }
} }
impl<T: Copy> From<T> for LogicalVec2<T> {
fn from(value: T) -> Self {
Self {
inline: value,
block: value,
}
}
}
impl<T> LogicalVec2<T> { impl<T> LogicalVec2<T> {
pub(crate) fn as_ref(&self) -> LogicalVec2<&T> {
LogicalVec2 {
inline: &self.inline,
block: &self.block,
}
}
pub fn map_inline_and_block_axes<U>( pub fn map_inline_and_block_axes<U>(
&self, &self,
inline_f: impl FnOnce(&T) -> U, inline_f: impl FnOnce(&T) -> U,

View file

@ -536,12 +536,25 @@ impl HoistedAbsolutelyPositionedBox {
inline: inline_axis_solver.inset_sum(), inline: inline_axis_solver.inset_sum(),
block: block_axis_solver.inset_sum(), block: block_axis_solver.inset_sum(),
}; };
let automatic_size = |alignment: AlignFlags, offsets: &AbsoluteBoxOffsets| {
if alignment.value() == AlignFlags::STRETCH && !offsets.either_auto() {
Size::Stretch
} else {
Size::FitContent
}
};
let used_size = replaced.used_size_as_if_inline_element_from_content_box_sizes( let used_size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
containing_block, containing_block,
&style, &style,
context.preferred_aspect_ratio(&pbm.padding_border_sums), context.preferred_aspect_ratio(&pbm.padding_border_sums),
&block_axis_solver.computed_sizes, LogicalVec2 {
&inline_axis_solver.computed_sizes, inline: &inline_axis_solver.computed_sizes,
block: &block_axis_solver.computed_sizes,
},
LogicalVec2 {
inline: automatic_size(inline_alignment, &inline_axis_solver.box_offsets),
block: automatic_size(block_alignment, &block_axis_solver.box_offsets),
},
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums, pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
); );
inline_axis_solver.override_size(used_size.inline); inline_axis_solver.override_size(used_size.inline);

View file

@ -440,8 +440,8 @@ impl ReplacedContents {
containing_block, containing_block,
style, style,
self.preferred_aspect_ratio(style, &pbm.padding_border_sums), self.preferred_aspect_ratio(style, &pbm.padding_border_sums),
&content_box_sizes_and_pbm.content_box_sizes.block, content_box_sizes_and_pbm.content_box_sizes.as_ref(),
&content_box_sizes_and_pbm.content_box_sizes.inline, Size::FitContent.into(),
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(), pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
) )
} }
@ -486,8 +486,8 @@ impl ReplacedContents {
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
style: &ComputedValues, style: &ComputedValues,
preferred_aspect_ratio: Option<AspectRatio>, preferred_aspect_ratio: Option<AspectRatio>,
block_sizes: &Sizes, sizes: LogicalVec2<&Sizes>,
inline_sizes: &Sizes, automatic_size: LogicalVec2<Size<Au>>,
pbm_sums: LogicalVec2<Au>, pbm_sums: LogicalVec2<Au>,
) -> LogicalVec2<Au> { ) -> LogicalVec2<Au> {
// <https://drafts.csswg.org/css-images-3/#natural-dimensions> // <https://drafts.csswg.org/css-images-3/#natural-dimensions>
@ -519,8 +519,11 @@ impl ReplacedContents {
// through the aspect ratio, but these can also be intrinsic and depend on the inline size. // through the aspect ratio, but these can also be intrinsic and depend on the inline size.
// Therefore, we tentatively treat intrinsic block sizing properties as their initial value. // Therefore, we tentatively treat intrinsic block sizing properties as their initial value.
let get_inline_content_size = || { let get_inline_content_size = || {
let get_block_size = let get_block_size = || {
|| block_sizes.resolve_extrinsic(Size::FitContent, Au::zero(), block_stretch_size); sizes
.block
.resolve_extrinsic(automatic_size.block, Au::zero(), block_stretch_size)
};
self.content_size( self.content_size(
Direction::Inline, Direction::Inline,
preferred_aspect_ratio, preferred_aspect_ratio,
@ -529,8 +532,8 @@ impl ReplacedContents {
) )
.into() .into()
}; };
let (preferred_inline, min_inline, max_inline) = inline_sizes.resolve_each( let (preferred_inline, min_inline, max_inline) = sizes.inline.resolve_each(
Size::FitContent, automatic_size.inline,
Au::zero(), Au::zero(),
inline_stretch_size, inline_stretch_size,
get_inline_content_size, get_inline_content_size,
@ -540,7 +543,7 @@ impl ReplacedContents {
// Now we can compute the block size, using the inline size from above. // Now we can compute the block size, using the inline size from above.
let block_content_size = LazyCell::new(|| -> ContentSizes { let block_content_size = LazyCell::new(|| -> ContentSizes {
let get_inline_size = || { let get_inline_size = || {
if inline_sizes.preferred.is_initial() { if sizes.inline.preferred.is_initial() {
// TODO: do we really need to special-case `auto`? // TODO: do we really need to special-case `auto`?
// https://github.com/w3c/csswg-drafts/issues/11236 // https://github.com/w3c/csswg-drafts/issues/11236
SizeConstraint::MinMax(min_inline, max_inline) SizeConstraint::MinMax(min_inline, max_inline)
@ -556,8 +559,8 @@ impl ReplacedContents {
) )
.into() .into()
}); });
let block_size = block_sizes.resolve( let block_size = sizes.block.resolve(
Size::FitContent, automatic_size.block,
Au::zero(), Au::zero(),
block_stretch_size.unwrap_or_else(|| block_content_size.max_content), block_stretch_size.unwrap_or_else(|| block_content_size.max_content),
|| *block_content_size, || *block_content_size,

View file

@ -161,16 +161,19 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
style, style,
independent_context independent_context
.preferred_aspect_ratio(&pbm.padding_border_sums), .preferred_aspect_ratio(&pbm.padding_border_sums),
&Sizes::new( LogicalVec2 {
block: &Sizes::new(
option_f32_to_size(content_box_known_dimensions.height), option_f32_to_size(content_box_known_dimensions.height),
Size::Initial, Size::Initial,
Size::Initial, Size::Initial,
), ),
&Sizes::new( inline: &Sizes::new(
option_f32_to_size(content_box_known_dimensions.width), option_f32_to_size(content_box_known_dimensions.width),
Size::Initial, Size::Initial,
Size::Initial, Size::Initial,
), ),
},
Size::FitContent.into(),
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(), pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
) )
.to_physical_size(self.style.writing_mode); .to_physical_size(self.style.writing_mode);

View file

@ -13,9 +13,3 @@
[.item 10] [.item 10]
expected: FAIL expected: FAIL
[.item 11]
expected: FAIL
[.item 12]
expected: FAIL

View file

@ -13,9 +13,3 @@
[.item 10] [.item 10]
expected: FAIL expected: FAIL
[.item 11]
expected: FAIL
[.item 12]
expected: FAIL

View file

@ -16,6 +16,3 @@
[.item 11] [.item 11]
expected: FAIL expected: FAIL
[.item 12]
expected: FAIL

View file

@ -16,6 +16,3 @@
[.item 11] [.item 11]
expected: FAIL expected: FAIL
[.item 12]
expected: FAIL