mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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 <obrufau@igalia.com>
This commit is contained in:
parent
64e227005f
commit
1966ab182f
4 changed files with 110 additions and 27 deletions
|
@ -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,
|
||||
);
|
||||
|
|
7
tests/wpt/meta/MANIFEST.json
vendored
7
tests/wpt/meta/MANIFEST.json
vendored
|
@ -576237,6 +576237,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"flex-basis-013.html": [
|
||||
"c11624a47eb07f9b46affbb735cb707c6aec600d",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"flex-basis-intrinsics-001.html": [
|
||||
"164abd82e5fb6c2dd140347287613888f23b2599",
|
||||
[
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-026.html]
|
||||
expected: FAIL
|
80
tests/wpt/tests/css/css-flexbox/flex-basis-013.html
vendored
Normal file
80
tests/wpt/tests/css/css-flexbox/flex-basis-013.html
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: flex base size that depends on cross size</title>
|
||||
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#flex-base-size">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#definite-sizes">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11791">
|
||||
<meta name="assert" content="The flex item has a definite cross size of 100px
|
||||
because it stretches. So the canvas can resolve its percentage against that,
|
||||
and thus the intrinsic flex basis results in a flex base size of 100px.">
|
||||
|
||||
<style>
|
||||
.container {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: red;
|
||||
margin: 5px;
|
||||
}
|
||||
.container.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
.item {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background: green;
|
||||
}
|
||||
.container.column .stretch-size {
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: stretch;
|
||||
}
|
||||
.container.row .stretch-size {
|
||||
height: -moz-available;
|
||||
height: -webkit-fill-available;
|
||||
height: stretch;
|
||||
}
|
||||
.container.column canvas {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.container.row canvas {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="tests"></div>
|
||||
<div id="log"></div>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/check-layout-th.js"></script>
|
||||
<script>
|
||||
let canvas = document.createElement("canvas");
|
||||
canvas.width = canvas.height = "5";
|
||||
|
||||
let item = document.createElement("div");
|
||||
item.appendChild(canvas);
|
||||
item.dataset.expectedWidth = item.dataset.expectedHeight = "50";
|
||||
|
||||
let container = document.createElement("div");
|
||||
container.appendChild(item);
|
||||
|
||||
let tests = document.getElementById("tests");
|
||||
|
||||
for (let direction of ["row", "column"]) {
|
||||
container.className = "container " + direction;
|
||||
for (let stretchSize of [false, true]) {
|
||||
item.className = "item" + (stretchSize ? " stretch-size" : "");
|
||||
for (let flexBasis of ["auto", "content", "min-content", "fit-content", "max-content"]) {
|
||||
item.style.flexBasis = flexBasis;
|
||||
tests.appendChild(container.cloneNode(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkLayout(".container");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue