diff --git a/RELEASES.md b/RELEASES.md
index 811ec88f9..c76236dda 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -5,6 +5,7 @@
### Fixes
- Content alignment (`align-content`/`justify-content`) behaviour was updated to match the latest spec (and Chrome 123+) (#635)
+- Ensure that root Flexbox nodes are floored by their padding-border (#651, #655)
## 0.4.3
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index 94eb74927..464cd0a91 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -1,6 +1,4 @@
//! Computes the [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) layout algorithm on [`TaffyTree`](crate::TaffyTree) according to the [spec](https://www.w3.org/TR/css-flexbox-1/)
-use core::ops::Add;
-
use crate::compute::common::alignment::compute_alignment_offset;
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{
@@ -163,6 +161,9 @@ pub fn compute_flexbox_layout(tree: &mut impl LayoutPartialTree, node: NodeId, i
let aspect_ratio = style.aspect_ratio;
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
+ let padding = style.padding.resolve_or_zero(parent_size.width);
+ let border = style.border.resolve_or_zero(parent_size.width);
+ let padding_border_sum = padding.sum_axes() + border.sum_axes();
let clamped_style_size = if inputs.sizing_mode == SizingMode::InherentSize {
style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
} else {
@@ -175,16 +176,9 @@ pub fn compute_flexbox_layout(tree: &mut impl LayoutPartialTree, node: NodeId, i
_ => None,
});
- // if the sum of the padding and border is greater than the size of the container, the
- // the result overwrites the size of the container
- let padding_border_sum = style
- .padding
- .resolve_or_zero(parent_size.width)
- .sum_axes()
- .add(style.border.resolve_or_zero(parent_size.width).sum_axes());
-
+ // The size of the container should be floored by the padding and border
let styled_based_known_dimensions =
- known_dimensions.or(min_max_definite_size).or(clamped_style_size).maybe_max(padding_border_sum);
+ known_dimensions.or(min_max_definite_size.or(clamped_style_size).maybe_max(padding_border_sum));
// Short-circuit layout if the container's size is fully determined by the container's size and the run mode
// is ComputeSize (and thus the container's size is all that we're interested in)
@@ -2185,10 +2179,9 @@ mod tests {
use crate::{
geometry::Size,
- prelude::{length, TaffyMaxContent},
style::{FlexWrap, Style},
util::{MaybeMath, ResolveOrZero},
- Rect, TaffyTree,
+ TaffyTree,
};
// Make sure we get correct constants
@@ -2227,31 +2220,4 @@ mod tests {
assert_eq!(constants.container_size, Size::zero());
assert_eq!(constants.inner_container_size, Size::zero());
}
-
- #[test]
- pub fn test_padding_and_border_larger_than_definite_size() {
- let mut tree: TaffyTree<()> = TaffyTree::with_capacity(16);
-
- let child = tree.new_leaf(Style::default()).unwrap();
-
- let root = tree
- .new_with_children(
- Style {
- size: Size { width: length(10.0), height: length(10.0) },
- padding: Rect { left: length(10.0), right: length(10.0), top: length(10.0), bottom: length(10.0) },
-
- border: Rect { left: length(10.0), right: length(10.0), top: length(10.0), bottom: length(10.0) },
- ..Default::default()
- },
- &[child],
- )
- .unwrap();
-
- tree.compute_layout(root, Size::MAX_CONTENT).unwrap();
-
- let layout = tree.layout(root).unwrap();
-
- assert_eq!(layout.size.width, 40.0);
- assert_eq!(layout.size.height, 40.0);
- }
}
diff --git a/test_fixtures/flex/padding_border_overrides_size_root.html b/test_fixtures/flex/padding_border_overrides_size_root.html
new file mode 100644
index 000000000..9dbcfe951
--- /dev/null
+++ b/test_fixtures/flex/padding_border_overrides_size_root.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ Test description
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/generated/flex/mod.rs b/tests/generated/flex/mod.rs
index 6e427742d..b2f6d34c4 100644
--- a/tests/generated/flex/mod.rs
+++ b/tests/generated/flex/mod.rs
@@ -425,6 +425,7 @@ mod padding_border_overrides_min_size;
mod padding_border_overrides_size;
mod padding_border_overrides_size_flex_basis_0;
mod padding_border_overrides_size_flex_basis_0_growable;
+mod padding_border_overrides_size_root;
mod padding_center_child;
mod padding_container_match_child;
mod padding_flex_child;
diff --git a/tests/generated/flex/padding_border_overrides_size_root.rs b/tests/generated/flex/padding_border_overrides_size_root.rs
new file mode 100644
index 000000000..33f2844fb
--- /dev/null
+++ b/tests/generated/flex/padding_border_overrides_size_root.rs
@@ -0,0 +1,83 @@
+#[test]
+fn padding_border_overrides_size_root() {
+ #[allow(unused_imports)]
+ use taffy::{prelude::*, tree::Layout, TaffyTree};
+ let mut taffy: TaffyTree = TaffyTree::new();
+ let node0 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Length(12f32),
+ height: taffy::style::Dimension::Length(12f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Length(8f32),
+ right: taffy::style::LengthPercentage::Length(4f32),
+ top: taffy::style::LengthPercentage::Length(2f32),
+ bottom: taffy::style::LengthPercentage::Length(6f32),
+ },
+ border: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Length(7f32),
+ right: taffy::style::LengthPercentage::Length(3f32),
+ top: taffy::style::LengthPercentage::Length(1f32),
+ bottom: taffy::style::LengthPercentage::Length(5f32),
+ },
+ ..Default::default()
+ },
+ &[node0],
+ )
+ .unwrap();
+ taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+ println!("\nComputed tree:");
+ taffy.print_tree(node);
+ println!();
+ #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+ let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 22f32, "width of node {:?}. Expected {}. Actual {}", node, 22f32, size.width);
+ assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node, 14f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+ #[cfg(feature = "content_size")]
+ assert_eq!(
+ layout.scroll_width(),
+ 0f32,
+ "scroll_width of node {:?}. Expected {}. Actual {}",
+ node,
+ 0f32,
+ layout.scroll_width()
+ );
+ #[cfg(feature = "content_size")]
+ assert_eq!(
+ layout.scroll_height(),
+ 0f32,
+ "scroll_height of node {:?}. Expected {}. Actual {}",
+ node,
+ 0f32,
+ layout.scroll_height()
+ );
+ #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+ let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+ assert_eq!(size.width, 0f32, "width of node {:?}. Expected {}. Actual {}", node0, 0f32, size.width);
+ assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0, 0f32, size.height);
+ assert_eq!(location.x, 15f32, "x of node {:?}. Expected {}. Actual {}", node0, 15f32, location.x);
+ assert_eq!(location.y, 3f32, "y of node {:?}. Expected {}. Actual {}", node0, 3f32, location.y);
+ #[cfg(feature = "content_size")]
+ assert_eq!(
+ layout.scroll_width(),
+ 0f32,
+ "scroll_width of node {:?}. Expected {}. Actual {}",
+ node0,
+ 0f32,
+ layout.scroll_width()
+ );
+ #[cfg(feature = "content_size")]
+ assert_eq!(
+ layout.scroll_height(),
+ 0f32,
+ "scroll_height of node {:?}. Expected {}. Actual {}",
+ node0,
+ 0f32,
+ layout.scroll_height()
+ );
+}
diff --git a/tests/root_constraints.rs b/tests/root_constraints.rs
index 9216118d2..631751d48 100644
--- a/tests/root_constraints.rs
+++ b/tests/root_constraints.rs
@@ -1,7 +1,7 @@
#[cfg(test)]
mod root_constraints {
- use taffy::style::AvailableSpace;
- use taffy::TaffyTree;
+ use taffy::style_helpers::{length, TaffyMaxContent};
+ use taffy::{AvailableSpace, Rect, Size, Style, TaffyTree};
#[test]
fn root_with_percentage_size() {
@@ -78,4 +78,31 @@ mod root_constraints {
assert_eq!(layout.size.width, 200.0);
assert_eq!(layout.size.height, 200.0);
}
+
+ #[test]
+ fn root_padding_and_border_larger_than_definite_size() {
+ let mut tree: TaffyTree<()> = TaffyTree::with_capacity(16);
+
+ let child = tree.new_leaf(Style::default()).unwrap();
+
+ let root = tree
+ .new_with_children(
+ Style {
+ size: Size { width: length(10.0), height: length(10.0) },
+ padding: Rect { left: length(10.0), right: length(10.0), top: length(10.0), bottom: length(10.0) },
+
+ border: Rect { left: length(10.0), right: length(10.0), top: length(10.0), bottom: length(10.0) },
+ ..Default::default()
+ },
+ &[child],
+ )
+ .unwrap();
+
+ tree.compute_layout(root, Size::MAX_CONTENT).unwrap();
+
+ let layout = tree.layout(root).unwrap();
+
+ assert_eq!(layout.size.width, 40.0);
+ assert_eq!(layout.size.height, 40.0);
+ }
}