Taffy API Reference
Taffy is a high-performance UI layout library implementing CSS Flexbox, Grid, and Block algorithms in Rust.
Quick Start
rust
use taffy::prelude::*;
let mut taffy: TaffyTree<()> = TaffyTree::new();
// Create nodes
let child = taffy.new_leaf(Style {
size: Size { width: length(100.0), height: auto() },
flex_grow: 1.0,
..Default::default()
})?;
let root = taffy.new_with_children(
Style {
display: Display::Flex,
size: Size { width: length(800.0), height: length(600.0) },
..Default::default()
},
&[child],
)?;
// Compute and access layout
taffy.compute_layout(root, Size::MAX_CONTENT)?;
let layout = taffy.layout(root)?;
println!("Position: ({}, {})", layout.location.x, layout.location.y);
println!("Size: {}x{}", layout.size.width, layout.size.height);
Core Types
TaffyTree<NodeContext>
Main entry point. NodeContext is user data for measure functions (use () if not needed).
rust
// Creation TaffyTree::new() // Default capacity (16) TaffyTree::with_capacity(100) // Pre-allocate // Node creation new_leaf(style) -> NodeId new_leaf_with_context(style, ctx) -> NodeId new_with_children(style, &[children]) -> NodeId // Tree manipulation add_child(parent, child) set_children(parent, &[children]) remove_child(parent, child) remove_child_at_index(parent, idx) insert_child_at_index(parent, idx, child) replace_child_at_index(parent, idx, new_child) // Style access set_style(node, style) style(node) -> &Style // Layout compute_layout(node, available_space) compute_layout_with_measure(node, available_space, measure_fn) layout(node) -> &Layout mark_dirty(node) // Invalidate cached layout dirty(node) -> bool // Check if needs recompute // Rounding enable_rounding() // Default: enabled disable_rounding() // Debug print_tree(root) // Print layout tree (std feature)
Layout (Output)
rust
pub struct Layout {
pub location: Point<f32>, // Top-left position relative to parent
pub size: Size<f32>, // Width and height
pub content_size: Size<f32>, // Content size (for scroll)
pub padding: Rect<f32>,
pub border: Rect<f32>,
pub margin: Rect<f32>,
pub scrollbar_size: Size<f32>,
pub order: u32, // Render order (higher = on top)
}
// Convenience methods
layout.content_box_size() // Size minus padding/border
layout.content_box_x() // X offset to content box
layout.content_box_y() // Y offset to content box
layout.scroll_width() // Overflow width
layout.scroll_height() // Overflow height
Geometry Types
rust
Size<T> { width: T, height: T }
Point<T> { x: T, y: T }
Rect<T> { left: T, right: T, top: T, bottom: T }
Line<T> { start: T, end: T }
// Constants
Size::ZERO, Size::MAX_CONTENT
Point::ZERO
Style Properties
Display Mode
rust
Display::Flex // Flexbox (default) Display::Grid // CSS Grid Display::Block // Block layout Display::None // Hidden
Position
rust
Position::Relative // Normal flow (default) Position::Absolute // Out of flow, relative to positioned ancestor
Sizing
rust
Style {
size: Size { width: length(100.0), height: auto() },
min_size: Size::auto(),
max_size: Size::auto(),
aspect_ratio: Some(16.0 / 9.0), // Width / height
box_sizing: BoxSizing::BorderBox, // or ContentBox
..Default::default()
}
Dimension Values
rust
// Helper functions (preferred) length(100.0) // Fixed pixels percent(0.5) // 50% of parent auto() // Automatic sizing min_content() // Shrink to minimum max_content() // Expand to maximum fit_content(length(200.0)) // Clamp to argument // Direct enum usage Dimension::Length(100.0) Dimension::Percent(0.5) Dimension::Auto
Spacing
rust
Style {
margin: Rect { left: length(10.0), right: length(10.0), top: auto(), bottom: auto() },
padding: Rect::length(20.0), // All sides same
border: Rect::zero(),
gap: Size { width: length(10.0), height: length(10.0) }, // Flex/Grid gap
..Default::default()
}
Overflow
rust
Style {
overflow: Point { x: Overflow::Visible, y: Overflow::Scroll },
scrollbar_width: 15.0, // Reserve space for scrollbar
..Default::default()
}
Overflow::Visible // Content can overflow (default)
Overflow::Clip // Clip overflow, auto min-size based on content
Overflow::Hidden // Clip overflow, auto min-size is 0
Overflow::Scroll // Like Hidden + reserve scrollbar space
Flexbox
rust
Style {
display: Display::Flex,
flex_direction: FlexDirection::Row, // Row, Column, RowReverse, ColumnReverse
flex_wrap: FlexWrap::NoWrap, // NoWrap, Wrap, WrapReverse
// Container alignment
justify_content: Some(JustifyContent::Center),
align_items: Some(AlignItems::Stretch),
align_content: Some(AlignContent::FlexStart),
gap: Size { width: length(10.0), height: length(10.0) },
..Default::default()
}
// Item properties
Style {
flex_grow: 1.0, // How much to grow (default: 0)
flex_shrink: 1.0, // How much to shrink (default: 1)
flex_basis: auto(), // Initial size before grow/shrink
align_self: Some(AlignSelf::Center),
..Default::default()
}
Alignment Values
rust
// justify_content / align_content JustifyContent::FlexStart | Start | Center | FlexEnd | End JustifyContent::SpaceBetween | SpaceAround | SpaceEvenly | Stretch // align_items / align_self AlignItems::FlexStart | Start | Center | FlexEnd | End AlignItems::Stretch | Baseline
CSS Grid
rust
Style {
display: Display::Grid,
// Track definitions
grid_template_columns: vec![length(250.0), fr(1.0), length(250.0)],
grid_template_rows: vec![length(100.0), fr(1.0), length(50.0)],
// Implicit tracks (for auto-placed items)
grid_auto_rows: vec![length(50.0)],
grid_auto_columns: vec![fr(1.0)],
grid_auto_flow: GridAutoFlow::Row, // Row, Column, RowDense, ColumnDense
// Alignment
justify_items: Some(AlignItems::Stretch),
align_items: Some(AlignItems::Stretch),
gap: Size { width: length(10.0), height: length(10.0) },
..Default::default()
}
Track Sizing Functions
rust
length(100.0) // Fixed size
percent(0.25) // Percentage of container
fr(1.0) // Fractional unit (flex)
auto() // Size to content
min_content() // Minimum content size
max_content() // Maximum content size
minmax(length(100.0), fr(1.0)) // Min/max bounds
fit_content(length(200.0)) // Clamp max-content to argument
flex(1.0) // Shorthand for minmax(0, fr(1))
// Repetition
repeat(3, vec![fr(1.0)]) // Repeat 3 times
repeat("auto-fill", vec![length(100.0)]) // Fill container
repeat("auto-fit", vec![minmax(length(100.0), fr(1.0))])
evenly_sized_tracks(4) // 4 equal columns: repeat(4, fr(1))
Grid Item Placement
rust
Style {
// Place on specific lines (1-indexed, negative counts from end)
grid_row: Line { start: line(1), end: line(3) },
grid_column: Line { start: line(2), end: span(2) },
// Item alignment
justify_self: Some(AlignSelf::Center),
align_self: Some(AlignSelf::Start),
..Default::default()
}
// Placement helpers
line(2) // Grid line 2
line(-1) // Last grid line
span(3) // Span 3 tracks
auto() // Auto placement
Holy Grail Layout Example
rust
let root = taffy.new_with_children(
Style {
display: Display::Grid,
size: Size { width: length(800.0), height: length(600.0) },
grid_template_columns: vec![length(200.0), fr(1.0), length(200.0)],
grid_template_rows: vec![length(100.0), fr(1.0), length(50.0)],
..Default::default()
},
&[header, left_sidebar, content, right_sidebar, footer],
)?;
// Header spans all 3 columns
let header = taffy.new_leaf(Style {
grid_row: line(1),
grid_column: Line { start: line(1), end: span(3) },
..Default::default()
})?;
Measure Functions
For leaf nodes with dynamic content (text, images):
rust
enum NodeContext {
Text(String),
Image { width: f32, height: f32 },
}
let text_node = taffy.new_leaf_with_context(
Style::default(),
NodeContext::Text("Hello".into()),
)?;
taffy.compute_layout_with_measure(
root,
Size::MAX_CONTENT,
|known_dimensions, available_space, node_id, node_context, style| {
match node_context {
Some(NodeContext::Text(text)) => measure_text(text, available_space),
Some(NodeContext::Image { width, height }) => Size { width: *width, height: *height },
None => Size::ZERO,
}
},
)?;
Measure Function Signature
rust
fn measure(
known_dimensions: Size<Option<f32>>, // Fixed dimensions (if any)
available_space: Size<AvailableSpace>, // Space constraints
node_id: NodeId,
node_context: Option<&mut NodeContext>,
style: &Style,
) -> Size<f32>
AvailableSpace
rust
AvailableSpace::Definite(500.0) // Exact available width/height
AvailableSpace::MinContent // Return minimum size
AvailableSpace::MaxContent // Return ideal size
// Common patterns
Size::MAX_CONTENT // Both axes max-content
Size { width: AvailableSpace::Definite(100.0), height: AvailableSpace::MaxContent }
Feature Flags
toml
[dependencies]
taffy = { version = "0.7", default-features = false, features = ["flexbox", "grid"] }
| Feature | Description |
|---|---|
flexbox | Flexbox layout (default) |
grid | CSS Grid layout (default) |
block_layout | Block layout (default) |
taffy_tree | Built-in tree (default) |
std | Standard library (default) |
alloc | Alloc without std |
serde | Serialization |
content_size | Track content size (default) |
detailed_layout_info | Grid track info |
Common Patterns
Centered Content
rust
Style {
display: Display::Flex,
justify_content: Some(JustifyContent::Center),
align_items: Some(AlignItems::Center),
..Default::default()
}
Scrollable Container
rust
Style {
overflow: Point { x: Overflow::Hidden, y: Overflow::Scroll },
scrollbar_width: 15.0,
..Default::default()
}
Absolute Positioning
rust
Style {
position: Position::Absolute,
inset: Rect {
left: length(10.0),
top: length(10.0),
right: auto(),
bottom: auto(),
},
..Default::default()
}
Responsive Grid
rust
Style {
display: Display::Grid,
grid_template_columns: vec![
repeat("auto-fill", vec![minmax(length(200.0), fr(1.0))])
],
gap: Size::length(16.0),
..Default::default()
}
Low-Level API
For custom tree implementations, implement these traits:
rust
trait TraversePartialTree {
fn child_ids(&self, node: NodeId) -> impl Iterator<Item = NodeId>;
fn child_count(&self, node: NodeId) -> usize;
fn get_child_id(&self, node: NodeId, index: usize) -> NodeId;
}
trait LayoutPartialTree: TraversePartialTree {
fn get_core_container_style(&self, node: NodeId) -> impl CoreStyle;
fn set_unrounded_layout(&mut self, node: NodeId, layout: &Layout);
fn compute_child_layout(&mut self, node: NodeId, inputs: LayoutInput) -> LayoutOutput;
}
Then use the algorithm functions directly:
rust
compute_flexbox_layout(&mut tree, node_id, inputs) compute_grid_layout(&mut tree, node_id, inputs) compute_block_layout(&mut tree, node_id, inputs) compute_leaf_layout(inputs, style, baseline_fn, measure_fn) round_layout(&mut tree, node_id)