Fix inset being incorrectly applied to `position:relative` flex items when both insets were set in a given axis (#348)
* Fix application of inset of relatively position flex nodes when both top and bottom or both left and right are specified
* Tests for relative inset conflicts
* Update changelog
ec371711989b7f4d870d91bea4b66bdd94b45c9e · por Nico Burns · 2023-02-03T20:43:01Z (hace 3 años) · padre ab747b81e · ver el árbol en este commit
Delta semántico · 14
benches/generated/flex_column_relative_all_sides.rs
benches/generated/flex_row_relative_all_sides.rs
benches/generated/grid_relative_all_sides.rs
tests/generated/flex_column_relative_all_sides.rs
tests/generated/flex_row_relative_all_sides.rs
tests/generated/grid_relative_all_sides.rs
diff --git a/RELEASES.md b/RELEASES.md
index 419cb094c..8861aaab4 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -16,6 +16,7 @@
- Aspect ratio is now applied correctly in many circumstances
- Absolutely positioned items now apply margins correctly
- Min/max size are now applied correctly
+- Inset applied incorrectly to relatively positioned flexbox children when both `top` and `bottom` or `left` and `right` were specified (#348)
### Removed
diff --git a/benches/generated/flex_column_relative_all_sides.rs b/benches/generated/flex_column_relative_all_sides.rs
new file mode 100644
index 000000000..35a57b7cb
--- /dev/null
+++ b/benches/generated/flex_column_relative_all_sides.rs
@@ -0,0 +1,31 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/flex_row_relative_all_sides.rs b/benches/generated/flex_row_relative_all_sides.rs
new file mode 100644
index 000000000..b95cbfeb0
--- /dev/null
+++ b/benches/generated/flex_row_relative_all_sides.rs
@@ -0,0 +1,30 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/grid_relative_all_sides.rs b/benches/generated/grid_relative_all_sides.rs
new file mode 100644
index 000000000..81a26bc18
--- /dev/null
+++ b/benches/generated/grid_relative_all_sides.rs
@@ -0,0 +1,31 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ display: taffy::style::Display::Grid,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/mod.rs b/benches/generated/mod.rs
index 6dc849d6c..3f469d704 100644
--- a/benches/generated/mod.rs
+++ b/benches/generated/mod.rs
@@ -233,6 +233,7 @@ mod flex_basis_smaller_then_content_with_flex_grow_very_large_size;
mod flex_basis_unconstraint_column;
mod flex_basis_unconstraint_row;
mod flex_basis_zero_undefined_main_size;
+mod flex_column_relative_all_sides;
mod flex_direction_column;
mod flex_direction_column_no_height;
mod flex_direction_column_reverse;
@@ -256,6 +257,7 @@ mod flex_grow_within_constrained_min_max_column;
mod flex_grow_within_constrained_min_row;
mod flex_grow_within_max_width;
mod flex_root_ignored;
+mod flex_row_relative_all_sides;
mod flex_shrink_by_outer_margin_with_max_size;
mod flex_shrink_flex_grow_child_flex_shrink_other_child;
mod flex_shrink_flex_grow_row;
@@ -607,6 +609,8 @@ mod grid_placement_auto_negative;
#[cfg(feature = "grid")]
mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative;
#[cfg(feature = "grid")]
+mod grid_relative_all_sides;
+#[cfg(feature = "grid")]
mod grid_relayout_vertical_text;
#[cfg(feature = "grid")]
mod grid_repeat_integer;
@@ -960,6 +964,7 @@ fn benchmark(c: &mut Criterion) {
flex_basis_unconstraint_column::compute();
flex_basis_unconstraint_row::compute();
flex_basis_zero_undefined_main_size::compute();
+ flex_column_relative_all_sides::compute();
flex_direction_column::compute();
flex_direction_column_no_height::compute();
flex_direction_column_reverse::compute();
@@ -983,6 +988,7 @@ fn benchmark(c: &mut Criterion) {
flex_grow_within_constrained_min_row::compute();
flex_grow_within_max_width::compute();
flex_root_ignored::compute();
+ flex_row_relative_all_sides::compute();
flex_shrink_by_outer_margin_with_max_size::compute();
flex_shrink_flex_grow_child_flex_shrink_other_child::compute();
flex_shrink_flex_grow_row::compute();
@@ -1334,6 +1340,8 @@ fn benchmark(c: &mut Criterion) {
#[cfg(feature = "grid")]
grid_placement_definite_in_secondary_axis_with_fully_definite_negative::compute();
#[cfg(feature = "grid")]
+ grid_relative_all_sides::compute();
+ #[cfg(feature = "grid")]
grid_relayout_vertical_text::compute();
#[cfg(feature = "grid")]
grid_repeat_integer::compute();
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index f4cee05f2..b0379c935 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -1523,13 +1523,13 @@ fn calculate_flex_item(
let offset_main = *total_offset_main
+ item.offset_main
+ item.margin.main_start(direction)
- + (item.inset.main_start(direction).unwrap_or(0.0) - item.inset.main_end(direction).unwrap_or(0.0));
+ + (item.inset.main_start(direction).or(item.inset.main_end(direction).map(|pos| -pos)).unwrap_or(0.0));
let offset_cross = total_offset_cross
+ item.offset_cross
+ line_offset_cross
+ item.margin.cross_start(direction)
- + (item.inset.cross_start(direction).unwrap_or(0.0) - item.inset.cross_end(direction).unwrap_or(0.0));
+ + (item.inset.cross_start(direction).or(item.inset.cross_end(direction).map(|pos| -pos)).unwrap_or(0.0));
if direction.is_row() {
let baseline_offset_cross = total_offset_cross + item.offset_cross + item.margin.cross_start(direction);
diff --git a/test_fixtures/flex_column_relative_all_sides.html b/test_fixtures/flex_column_relative_all_sides.html
new file mode 100644
index 000000000..aa5a6b2a9
--- /dev/null
+++ b/test_fixtures/flex_column_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="height: 100px; width: 100px;flex-direction: column;">
+ <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/flex_row_relative_all_sides.html b/test_fixtures/flex_row_relative_all_sides.html
new file mode 100644
index 000000000..ea8f8b9fd
--- /dev/null
+++ b/test_fixtures/flex_row_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="height: 100px; width: 100px;">
+ <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/grid_relative_all_sides.html b/test_fixtures/grid_relative_all_sides.html
new file mode 100644
index 000000000..31388558c
--- /dev/null
+++ b/test_fixtures/grid_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid;height: 100px; width: 100px;">
+ <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated/flex_column_relative_all_sides.rs b/tests/generated/flex_column_relative_all_sides.rs
new file mode 100644
index 000000000..5a2891e6d
--- /dev/null
+++ b/tests/generated/flex_column_relative_all_sides.rs
@@ -0,0 +1,46 @@
+#[test]
+fn flex_column_relative_all_sides() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+ assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+ assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.height);
+ assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+ assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/flex_row_relative_all_sides.rs b/tests/generated/flex_row_relative_all_sides.rs
new file mode 100644
index 000000000..69bcb920e
--- /dev/null
+++ b/tests/generated/flex_row_relative_all_sides.rs
@@ -0,0 +1,45 @@
+#[test]
+fn flex_row_relative_all_sides() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+ assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.height);
+ assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+ assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/grid_relative_all_sides.rs b/tests/generated/grid_relative_all_sides.rs
new file mode 100644
index 000000000..a956627f3
--- /dev/null
+++ b/tests/generated/grid_relative_all_sides.rs
@@ -0,0 +1,46 @@
+#[test]
+fn grid_relative_all_sides() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+ inset: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(10f32),
+ right: taffy::style::LengthPercentageAuto::Points(10f32),
+ top: taffy::style::LengthPercentageAuto::Points(10f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ display: taffy::style::Display::Grid,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+ assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.height);
+ assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+ assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs
index 8ad7c04e8..d347ce174 100644
--- a/tests/generated/mod.rs
+++ b/tests/generated/mod.rs
@@ -232,6 +232,7 @@ mod flex_basis_smaller_then_content_with_flex_grow_very_large_size;
mod flex_basis_unconstraint_column;
mod flex_basis_unconstraint_row;
mod flex_basis_zero_undefined_main_size;
+mod flex_column_relative_all_sides;
mod flex_direction_column;
mod flex_direction_column_no_height;
mod flex_direction_column_reverse;
@@ -255,6 +256,7 @@ mod flex_grow_within_constrained_min_max_column;
mod flex_grow_within_constrained_min_row;
mod flex_grow_within_max_width;
mod flex_root_ignored;
+mod flex_row_relative_all_sides;
mod flex_shrink_by_outer_margin_with_max_size;
mod flex_shrink_flex_grow_child_flex_shrink_other_child;
mod flex_shrink_flex_grow_row;
@@ -606,6 +608,8 @@ mod grid_placement_auto_negative;
#[cfg(feature = "grid")]
mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative;
#[cfg(feature = "grid")]
+mod grid_relative_all_sides;
+#[cfg(feature = "grid")]
mod grid_relayout_vertical_text;
#[cfg(feature = "grid")]
mod grid_repeat_integer;