Preserve contained grid row stretch
This commit is contained in:
@@ -5374,6 +5374,12 @@ enum ContainerAutoInlineSize {
|
||||
StretchedGridItem,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum ContainerAutoBlockSize {
|
||||
Intrinsic,
|
||||
StretchedGridItem,
|
||||
}
|
||||
|
||||
/// Classify how an auto inline-size is resolved. Stretched grid items need
|
||||
/// their intrinsic contribution contained without replacing the final auto
|
||||
/// size that stretch alignment consumes.
|
||||
@@ -5455,6 +5461,55 @@ fn container_auto_inline_size(
|
||||
}
|
||||
}
|
||||
|
||||
/// Classify an auto block-size for size containment. A stretched grid item
|
||||
/// must keep its auto size so final alignment can fill a definite grid area;
|
||||
/// only its intrinsic track contribution is contained.
|
||||
fn container_auto_block_size(
|
||||
tree: &DomTree,
|
||||
id: NodeId,
|
||||
style: &crate::LayoutStyle,
|
||||
styles: &HashMap<NodeId, crate::LayoutStyle>,
|
||||
) -> ContainerAutoBlockSize {
|
||||
// Absolutely positioned descendants are not grid items. Preserve the
|
||||
// existing contained intrinsic-height behavior until their independent
|
||||
// inset-based fill sizing is modeled explicitly.
|
||||
if matches!(style.position, Some(taffy::Position::Absolute)) {
|
||||
return ContainerAutoBlockSize::Intrinsic;
|
||||
}
|
||||
|
||||
let mut parent = tree.get_node(id).and_then(|node| node.parent);
|
||||
let parent_style = loop {
|
||||
let Some(parent_id) = parent else {
|
||||
return ContainerAutoBlockSize::Intrinsic;
|
||||
};
|
||||
let Some(parent_style) = styles.get(&parent_id) else {
|
||||
return ContainerAutoBlockSize::Intrinsic;
|
||||
};
|
||||
if parent_style.display_contents {
|
||||
parent = tree.get_node(parent_id).and_then(|node| node.parent);
|
||||
continue;
|
||||
}
|
||||
break parent_style;
|
||||
};
|
||||
|
||||
if parent_style.display == crate::Display::Grid
|
||||
&& style
|
||||
.align_self
|
||||
.unwrap_or(
|
||||
parent_style
|
||||
.align_items
|
||||
.unwrap_or(taffy::AlignItems::STRETCH),
|
||||
)
|
||||
== taffy::AlignSelf::STRETCH
|
||||
&& !style.margin_auto[0]
|
||||
&& !style.margin_auto[2]
|
||||
{
|
||||
ContainerAutoBlockSize::StretchedGridItem
|
||||
} else {
|
||||
ContainerAutoBlockSize::Intrinsic
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply the used-size part of `container-type`'s implicit size containment.
|
||||
///
|
||||
/// The default contain-intrinsic-size is zero. Fill-available block boxes keep
|
||||
@@ -5499,7 +5554,14 @@ fn apply_container_size_containment(
|
||||
let ratio_transfers_block_size =
|
||||
style.aspect_ratio.is_some() && !matches!(style.width, crate::Dimension::Auto);
|
||||
if matches!(style.height, crate::Dimension::Auto) && !ratio_transfers_block_size {
|
||||
taffy_style.size.height = taffy::Dimension::length(0.0);
|
||||
match container_auto_block_size(tree, id, style, styles) {
|
||||
ContainerAutoBlockSize::Intrinsic => {
|
||||
taffy_style.size.height = taffy::Dimension::length(0.0);
|
||||
}
|
||||
ContainerAutoBlockSize::StretchedGridItem => {
|
||||
taffy_style.intrinsic_size_containment.height = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,6 +1147,63 @@ fn stretched_inline_size_container_has_zero_intrinsic_grid_contribution() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stretched_size_container_has_zero_intrinsic_grid_row_contribution() {
|
||||
// Chromium 140: block-axis size containment removes the tall child's
|
||||
// intrinsic row contribution, but leaves the grid item's auto height
|
||||
// available for final stretch alignment. Padding and border remain inside
|
||||
// the fixed row's stretched 100px border box.
|
||||
let tree = parse_html(
|
||||
r#"
|
||||
<style>
|
||||
html, body { margin: 0 }
|
||||
.grid { display: grid }
|
||||
.item { container-type: size }
|
||||
.child { width: 20px; height: 240px }
|
||||
#fixed-grid {
|
||||
margin-top: 20px;
|
||||
grid-template-rows: 100px;
|
||||
}
|
||||
#fixed-item {
|
||||
padding-block: 10px;
|
||||
border-top: 5px solid black;
|
||||
border-bottom: 5px solid black;
|
||||
}
|
||||
</style>
|
||||
<div id="shrink-grid" class="grid">
|
||||
<div id="shrink-item" class="item">
|
||||
<div id="shrink-child" class="child"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="fixed-grid" class="grid">
|
||||
<div id="fixed-item" class="item">
|
||||
<div id="fixed-child" class="child"></div>
|
||||
</div>
|
||||
</div>
|
||||
"#,
|
||||
);
|
||||
let layout = layout_dom(&tree, (800.0, 600.0));
|
||||
let rect = |id| layout.rects[&tree.get_element_by_id(id).unwrap()];
|
||||
let shrink_grid = rect("shrink-grid");
|
||||
let shrink_item = rect("shrink-item");
|
||||
let shrink_child = rect("shrink-child");
|
||||
let fixed_grid = rect("fixed-grid");
|
||||
let fixed_item = rect("fixed-item");
|
||||
let fixed_child = rect("fixed-child");
|
||||
assert!(
|
||||
shrink_grid.height.abs() < 0.01
|
||||
&& shrink_item.height.abs() < 0.01
|
||||
&& (shrink_child.height - 240.0).abs() < 0.01
|
||||
&& (fixed_grid.height - 100.0).abs() < 0.01
|
||||
&& (fixed_item.height - 100.0).abs() < 0.01
|
||||
&& (fixed_child.y - fixed_item.y - 15.0).abs() < 0.01
|
||||
&& (fixed_child.height - 240.0).abs() < 0.01,
|
||||
"contained intrinsic contribution leaked into the grid row: \
|
||||
shrink=({shrink_grid:?}, {shrink_item:?}, {shrink_child:?}) \
|
||||
fixed=({fixed_grid:?}, {fixed_item:?}, {fixed_child:?})"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_stretched_auto_grid_item_shrink_wraps_inside_grid_area() {
|
||||
let tree = parse_html(
|
||||
|
||||
Reference in New Issue
Block a user