1# taffy
2
3[](https://github.com/DioxusLabs/taffy/actions/workflows/ci.yml)
4[](https://crates.io/crates/taffy)
5[](https://docs.rs/taffy)
6
7`taffy` is a flexible, high-performance, cross-platform UI layout library written in [Rust](https://www.rust-lang.org).
8
9Currently, we only support a [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) layout algorithm, but support for other paradigms [is planned](https://github.com/DioxusLabs/taffy/issues/28).
10
11This crate is a collaborative, cross-team project, and is designed to be used as a dependency for other UI and GUI libraries.
12Right now, it powers:
13
14- [Dioxus](https://dioxuslabs.com/): a React-like library for building fast, portable, and beautiful user interfaces with Rust
15- [Bevy](https://bevyengine.org/): an ergonomic, ECS-first Rust game engine
16
17## Usage
18
19```rust
20use taffy::prelude::*;
21
22// First create an instance of Taffy
23let mut taffy = Taffy::new();
24
25// Create a tree of nodes using `taffy.new_leaf` and `taffy.new_with_children`.
26// These functions both return a node id which can be used to refer to that node
27// The Style struct is used to specify styling information
28let header_node = taffy
29 .new_leaf(
30 Style {
31 size: Size { width: points(800.0), height: points(100.0) },
32 ..Default::default()
33 },
34 ).unwrap();
35
36let body_node = taffy
37 .new_leaf(
38 Style {
39 size: Size { width: points(800.0), height: auto() },
40 flex_grow: 1.0,
41 ..Default::default()
42 },
43 ).unwrap();
44
45let root_node = taffy
46 .new_with_children(
47 Style {
48 flex_direction: FlexDirection::Column,
49 size: Size { width: points(800.0), height: points(600.0) },
50 ..Default::default()
51 },
52 &[header_node, body_node],
53 )
54 .unwrap();
55
56// Call compute_layout on the root of your tree to run the layout algorithm
57taffy.compute_layout(root_node, Size::MAX_CONTENT).unwrap();
58
59// Inspect the computed layout using taffy.layout
60assert_eq!(taffy.layout(root_node).unwrap().size.width, 800.0);
61assert_eq!(taffy.layout(root_node).unwrap().size.height, 600.0);
62assert_eq!(taffy.layout(header_node).unwrap().size.width, 800.0);
63assert_eq!(taffy.layout(header_node).unwrap().size.height, 100.0);
64assert_eq!(taffy.layout(body_node).unwrap().size.width, 800.0);
65assert_eq!(taffy.layout(body_node).unwrap().size.height, 500.0); // This value was not set explicitly, but was computed by Taffy
66
67```
68
69## Benchmarks (vs. [Yoga](https://github.com/facebook/yoga))
70
71- Run on a 2021 MacBook Pro with M1 Pro processor.
72- Taffy benchmarks are using criterion (10 iterations).
73- Yoga benchmarks run via it's node.js bindings (the `yoga-layout-prebuilt` npm package), they were run a few times manually and it was verified that variance in the numbers of each run was minimal. It should be noted that this is using an old version of Yoga.
74
75(note that the table below contains multiple different units (milliseconds vs. microseconds vs. nanoseconds))
76
77| Benchmark | Yoga | Taffy 0.2 |
78| --- | --- | --- |
79| yoga/10 nodes (1-level hierarchy) | 45.1670 µs | 1.9857 µs |
80| yoga/100 nodes (2-level hierarchy) | 134.1250 µs | 41.810 µs |
81| yoga/1_000 nodes (3-level hierarchy) | 1.2221 ms | 357.48 µs |
82| yoga/10_000 nodes (4-level hierarchy) | 13.8672 ms | 3.7310 ms |
83| yoga/100_000 nodes (5-level hierarchy) | 141.5307 ms | 39.682 ms |
84
85Most popular websites seem to have between 3,000 and 10,000 nodes (although they also require text layout, which neither yoga nor taffy implement).
86
87## Contributions
88
89[Contributions welcome](https://github.com/DioxusLabs/taffy/blob/main/CONTRIBUTING.md):
90if you'd like to use, improve or build `taffy`, feel free to join the conversation, open an [issue](https://github.com/DioxusLabs/taffy/issues) or submit a [PR](https://github.com/DioxusLabs/taffy/pulls).
91If you have questions about how to use `taffy`, open a [discussion](https://github.com/DioxusLabs/taffy/discussions) so we can answer your questions in a way that others can find.
README.md
taffy

taffy is a flexible, high-performance, cross-platform UI layout library written in Rust.
Currently, we only support a flexbox layout algorithm, but support for other paradigms is planned.
This crate is a collaborative, cross-team project, and is designed to be used as a dependency for other UI and GUI libraries.
Right now, it powers:
- Dioxus: a React-like library for building fast, portable, and beautiful user interfaces with Rust
- Bevy: an ergonomic, ECS-first Rust game engine
Usage
use taffy::prelude::*;
// First create an instance of Taffy
let mut taffy = Taffy::new();
// Create a tree of nodes using `taffy.new_leaf` and `taffy.new_with_children`.
// These functions both return a node id which can be used to refer to that node
// The Style struct is used to specify styling information
let header_node = taffy
.new_leaf(
Style {
size: Size { width: points(800.0), height: points(100.0) },
..Default::default()
},
).unwrap();
let body_node = taffy
.new_leaf(
Style {
size: Size { width: points(800.0), height: auto() },
flex_grow: 1.0,
..Default::default()
},
).unwrap();
let root_node = taffy
.new_with_children(
Style {
flex_direction: FlexDirection::Column,
size: Size { width: points(800.0), height: points(600.0) },
..Default::default()
},
&[header_node, body_node],
)
.unwrap();
// Call compute_layout on the root of your tree to run the layout algorithm
taffy.compute_layout(root_node, Size::MAX_CONTENT).unwrap();
// Inspect the computed layout using taffy.layout
assert_eq!(taffy.layout(root_node).unwrap().size.width, 800.0);
assert_eq!(taffy.layout(root_node).unwrap().size.height, 600.0);
assert_eq!(taffy.layout(header_node).unwrap().size.width, 800.0);
assert_eq!(taffy.layout(header_node).unwrap().size.height, 100.0);
assert_eq!(taffy.layout(body_node).unwrap().size.width, 800.0);
assert_eq!(taffy.layout(body_node).unwrap().size.height, 500.0); // This value was not set explicitly, but was computed by Taffy
Benchmarks (vs. Yoga)
- Run on a 2021 MacBook Pro with M1 Pro processor.
- Taffy benchmarks are using criterion (10 iterations).
- Yoga benchmarks run via it's node.js bindings (the
yoga-layout-prebuilt npm package), they were run a few times manually and it was verified that variance in the numbers of each run was minimal. It should be noted that this is using an old version of Yoga.
(note that the table below contains multiple different units (milliseconds vs. microseconds vs. nanoseconds))
| Benchmark | Yoga | Taffy 0.2 |
| yoga/10 nodes (1-level hierarchy) | 45.1670 µs | 1.9857 µs |
| yoga/100 nodes (2-level hierarchy) | 134.1250 µs | 41.810 µs |
| yoga/1_000 nodes (3-level hierarchy) | 1.2221 ms | 357.48 µs |
| yoga/10_000 nodes (4-level hierarchy) | 13.8672 ms | 3.7310 ms |
| yoga/100_000 nodes (5-level hierarchy) | 141.5307 ms | 39.682 ms |
Most popular websites seem to have between 3,000 and 10,000 nodes (although they also require text layout, which neither yoga nor taffy implement).
Contributions
Contributions welcome:
if you'd like to use, improve or build taffy, feel free to join the conversation, open an issue or submit a PR.
If you have questions about how to use taffy, open a discussion so we can answer your questions in a way that others can find.