tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Sutichaykuna

Add support for display: flow-root

89f50ccb7d37e4d4b78a8250eca82eeaf63ad3de · ruwaq nico.burns · (2 killa ñawpaq) · tayta 86d93d95b · kay commitpi sach'ata qhaway

Semántico sayk'uy · 10

benches/src/taffy_03_helpers.rs

benches/src/yoga_helpers.rs

src/style/mod.rs

  • silq'uyninpi t'ikrakurqan enum Display pub
  • ukhunpi t'ikrakurqan fn fmt

src/tree/taffy_tree.rs

tests/hand_written.rs

7 qillqakuna · +135 −0

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a479e60ce..907cbd1fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 ## Unreleased
 
+### Added
+
+- Support for `display: flow-root`. The new `Display::FlowRoot` variant lays out children using the block layout algorithm but always establishes a new block formatting context (its margins do not collapse with those of its children, it contains its own floats, and it avoids external floats)
+
 ### Fixed
 
 - Numeric style helpers (`length`, `percent`, `fr`, `flex`) now accept `Input: Into<f64>` instead of `Input: Into<f32>`. This allows bare float literals such as `length(800.0)` to be used without triggering the `float_literal_f32_fallback` future-compatibility lint, while widening the set of accepted numeric input types (#974)
diff --git a/benches/src/taffy_03_helpers.rs b/benches/src/taffy_03_helpers.rs
index 8ab461178..c93bd214f 100644
--- a/benches/src/taffy_03_helpers.rs
+++ b/benches/src/taffy_03_helpers.rs
@@ -154,6 +154,7 @@ fn convert_display(input: taffy::style::Display) -> taffy_03::style::Display {
         taffy::style::Display::Flex => taffy_03::style::Display::Flex,
         taffy::style::Display::Grid => taffy_03::style::Display::Grid,
         taffy::style::Display::Block => panic!("Block layout not implemented in taffy 0.3"),
+        taffy::style::Display::FlowRoot => panic!("Block layout not implemented in taffy 0.3"),
     }
 }
 
diff --git a/benches/src/yoga_helpers.rs b/benches/src/yoga_helpers.rs
index 9f61c34ae..586767ded 100644
--- a/benches/src/yoga_helpers.rs
+++ b/benches/src/yoga_helpers.rs
@@ -188,6 +188,7 @@ fn apply_taffy_style(node: &mut yg::Node, style: &tf::Style) {
         tf::Display::Flex => yg::Display::Flex,
         tf::Display::Grid => panic!("Yoga does not support CSS Grid layout"),
         tf::Display::Block => panic!("Yoga does not support CSS Block layout"),
+        tf::Display::FlowRoot => panic!("Yoga does not support CSS Block layout"),
     });
 
     // box_sizing
diff --git a/src/style/mod.rs b/src/style/mod.rs
index beba85251..bf349e5c6 100644
--- a/src/style/mod.rs
+++ b/src/style/mod.rs
@@ -185,6 +185,9 @@ pub enum Display {
     /// The children will follow the block layout algorithm
     #[cfg(feature = "block_layout")]
     Block,
+    /// The children will follow the block layout algorithm and establish a new block formatting context
+    #[cfg(feature = "block_layout")]
+    FlowRoot,
     /// The children will follow the flexbox layout algorithm
     #[cfg(feature = "flexbox")]
     Flex,
@@ -228,6 +231,8 @@ crate::util::parse::impl_parse_for_keyword_enum!(Display,
     "grid" => Grid,
     #[cfg(feature = "block_layout")]
     "block" => Block,
+    #[cfg(feature = "block_layout")]
+    "flow-root" => FlowRoot,
 );
 
 impl core::fmt::Display for Display {
@@ -236,6 +241,8 @@ impl core::fmt::Display for Display {
             Display::None => write!(f, "NONE"),
             #[cfg(feature = "block_layout")]
             Display::Block => write!(f, "BLOCK"),
+            #[cfg(feature = "block_layout")]
+            Display::FlowRoot => write!(f, "FLOW-ROOT"),
             #[cfg(feature = "flexbox")]
             Display::Flex => write!(f, "FLEX"),
             #[cfg(feature = "grid")]
diff --git a/src/tree/taffy_tree.rs b/src/tree/taffy_tree.rs
index ab9beb038..71a9fa735 100644
--- a/src/tree/taffy_tree.rs
+++ b/src/tree/taffy_tree.rs
@@ -236,6 +236,8 @@ impl<NodeContext> PrintTree for TaffyTree<NodeContext> {
             (0, _) => "LEAF",
             #[cfg(feature = "block_layout")]
             (_, Display::Block) => "BLOCK",
+            #[cfg(feature = "block_layout")]
+            (_, Display::FlowRoot) => "FLOW-ROOT",
             #[cfg(feature = "flexbox")]
             (_, Display::Flex) => {
                 use crate::FlexDirection;
@@ -311,6 +313,8 @@ where
                 (Display::None, _) => compute_hidden_layout(tree, node_id),
                 #[cfg(feature = "block_layout")]
                 (Display::Block, true) => compute_block_layout(tree, node_id, inputs, block_ctx),
+                #[cfg(feature = "block_layout")]
+                (Display::FlowRoot, true) => compute_block_layout(tree, node_id, inputs, None),
                 #[cfg(feature = "flexbox")]
                 (Display::Flex, true) => compute_flexbox_layout(tree, node_id, inputs),
                 #[cfg(feature = "grid")]
diff --git a/tests/hand_written.rs b/tests/hand_written.rs
index 8f1b996ee..55caf68fa 100644
--- a/tests/hand_written.rs
+++ b/tests/hand_written.rs
@@ -2,6 +2,7 @@ mod hand_written {
     mod border_and_padding;
     mod caching;
     mod floats;
+    mod flow_root;
     mod measure;
     mod min_max_overrides;
     mod relayout;
diff --git a/tests/hand_written/flow_root.rs b/tests/hand_written/flow_root.rs
new file mode 100644
index 000000000..4e4288b5b
--- /dev/null
+++ b/tests/hand_written/flow_root.rs
@@ -0,0 +1,117 @@
+#![cfg(all(feature = "block_layout", feature = "float_layout"))]
+
+use taffy::geometry::{Point, Rect, Size};
+use taffy::prelude::*;
+use taffy::style::Float;
+use taffy_test_helpers::new_test_tree;
+
+#[test]
+fn flow_root_does_not_collapse_margins_through_parent() {
+    let child_style = Style {
+        display: Display::Block,
+        size: Size { width: length(40.0), height: length(10.0) },
+        margin: Rect { top: length(20.0), bottom: length(30.0), ..Rect::zero() },
+        ..Default::default()
+    };
+
+    let mut taffy = new_test_tree();
+    let plain_child = taffy.new_leaf(child_style.clone()).unwrap();
+    let plain_parent = taffy
+        .new_with_children(
+            Style {
+                display: Display::Block,
+                size: Size { width: length(100.0), height: auto() },
+                ..Default::default()
+            },
+            &[plain_child],
+        )
+        .unwrap();
+
+    let flow_child = taffy.new_leaf(child_style).unwrap();
+    let flow_parent = taffy
+        .new_with_children(
+            Style {
+                display: Display::FlowRoot,
+                size: Size { width: length(100.0), height: auto() },
+                ..Default::default()
+            },
+            &[flow_child],
+        )
+        .unwrap();
+    let root = taffy
+        .new_with_children(
+            Style {
+                display: Display::Block,
+                size: Size { width: length(200.0), height: auto() },
+                ..Default::default()
+            },
+            &[plain_parent, flow_parent],
+        )
+        .unwrap();
+    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
+
+    assert_eq!(taffy.layout(plain_parent).unwrap().size.height, 10.0);
+    assert_eq!(taffy.layout(flow_parent).unwrap().size.height, 60.0);
+    assert_eq!(taffy.layout(flow_child).unwrap().location.y, 20.0);
+}
+
+#[test]
+fn flow_root_contains_floated_children() {
+    let mut taffy = new_test_tree();
+    let float = taffy
+        .new_leaf(Style {
+            display: Display::Block,
+            float: Float::Left,
+            size: Size { width: length(20.0), height: length(30.0) },
+            ..Default::default()
+        })
+        .unwrap();
+    let flow_root = taffy
+        .new_with_children(
+            Style {
+                display: Display::FlowRoot,
+                size: Size { width: length(100.0), height: auto() },
+                ..Default::default()
+            },
+            &[float],
+        )
+        .unwrap();
+    taffy.compute_layout(flow_root, Size::MAX_CONTENT).unwrap();
+
+    assert_eq!(taffy.layout(flow_root).unwrap().size.height, 30.0);
+}
+
+#[test]
+fn flow_root_sibling_avoids_float() {
+    let mut taffy = new_test_tree();
+    let float = taffy
+        .new_leaf(Style {
+            display: Display::Block,
+            float: Float::Left,
+            size: Size { width: length(30.0), height: length(20.0) },
+            ..Default::default()
+        })
+        .unwrap();
+    let flow_child =
+        taffy.new_leaf(Style { size: Size { width: auto(), height: length(10.0) }, ..Default::default() }).unwrap();
+    let flow_root = taffy
+        .new_with_children(
+            Style { display: Display::FlowRoot, size: Size { width: auto(), height: auto() }, ..Default::default() },
+            &[flow_child],
+        )
+        .unwrap();
+    let parent = taffy
+        .new_with_children(
+            Style {
+                display: Display::Block,
+                size: Size { width: length(100.0), height: auto() },
+                ..Default::default()
+            },
+            &[float, flow_root],
+        )
+        .unwrap();
+    taffy.compute_layout(parent, Size::MAX_CONTENT).unwrap();
+
+    assert_eq!(taffy.layout(flow_root).unwrap().location, Point { x: 30.0, y: 0.0 });
+    assert_eq!(taffy.layout(flow_root).unwrap().size.width, 70.0);
+}