Expand description
Layout and positioning in terminal user interfaces.
This module provides a comprehensive set of types and traits for working with layout and positioning in terminal applications. It implements a flexible layout system that allows you to divide the terminal screen into different areas using constraints, manage positioning and sizing, and handle complex UI arrangements.
The layout system in Ratatui is based on the Cassowary constraint solver algorithm, implemented
through the kasuari crate. This allows for sophisticated constraint-based layouts where
multiple requirements can be satisfied simultaneously, with priorities determining which
constraints take precedence when conflicts arise.
§Core Concepts
§Coordinate System
The coordinate system runs left to right, top to bottom, with the origin (0, 0) in the top
left corner of the terminal. The x and y coordinates are represented by u16 values.
x (columns)
┌─────────────→
y │ (0,0)
│
(rows)
↓§Layout Fundamentals
Layouts form the structural foundation of your terminal UI. The Layout struct divides
available screen space into rectangular areas using a constraint-based approach. You define
multiple constraints for how space should be allocated, and the Cassowary solver determines
the optimal layout that satisfies as many constraints as possible. These areas can then be
used to render widgets or nested layouts.
Note that the Layout struct is not required to create layouts - you can also manually
calculate and create Rect areas using simple mathematics to divide up the terminal space
if you prefer direct control over positioning and sizing.
§Rectangular Areas
All layout operations work with rectangular areas represented by the Rect type. A Rect
defines a position and size in the terminal, specified by its top-left corner coordinates and
dimensions.
§Available Types
§Core Layout Types
Layout- The primary layout engine that divides space using constraints and directionRect- Represents a rectangular area with position and dimensionsConstraint- Defines how space should be allocated (length, percentage, ratio, etc.)Direction- Specifies layout orientation (horizontal or vertical)Flex- Controls space distribution when constraints are satisfied
§Positioning and Sizing
Position- Represents a point in the terminal coordinate systemSize- Represents dimensions (width and height)Margin- Defines spacing around rectangular areasOffset- Represents relative movement in the coordinate systemSpacing- Controls spacing or overlap between layout segments
§Alignment
Alignment(alias forHorizontalAlignment) - Horizontal text/content alignmentHorizontalAlignment- Horizontal alignment options (left, center, right)VerticalAlignment- Vertical alignment options (top, center, bottom)
§Iteration Support
Rows- Iterator over horizontal rows within a rectangular areaColumns- Iterator over vertical columns within a rectangular areaPositions- Iterator over all positions within a rectangular area
§Quick Start
Here’s a simple example of creating a basic layout using the Layout struct:
use ratatui_core::layout::{Constraint, Direction, Layout, Rect};
// Create a terminal area
let area = Rect::new(0, 0, 80, 24);
// Divide it vertically into two equal parts using Layout
let layout = Layout::vertical([Constraint::Percentage(50), Constraint::Percentage(50)]);
let [top, bottom] = layout.areas(area);
// Now you have two areas: top and bottomNote: When the number of layout areas is known at compile time, use destructuring assignment with descriptive variable names for better readability:
use ratatui_core::layout::{Constraint, Layout, Rect};
let area = Rect::new(0, 0, 80, 24);
let [header, content, footer] = Layout::vertical([
Constraint::Length(3),
Constraint::Fill(1),
Constraint::Length(1),
])
.areas(area);Use Layout::split when the number of areas is only known at runtime.
Alternatively, you can create layouts manually using mathematics:
use ratatui_core::layout::Rect;
// Create a terminal area
let area = Rect::new(0, 0, 80, 24);
// Manually divide into two equal parts
let top_half = Rect::new(area.x, area.y, area.width, area.height / 2);
let bottom_half = Rect::new(
area.x,
area.y + area.height / 2,
area.width,
area.height / 2,
);§Layout Examples
§Basic Vertical Split
use ratatui_core::layout::{Constraint, Layout, Rect};
let area = Rect::new(0, 0, 80, 24);
let [header, content, footer] = Layout::vertical([
Constraint::Length(3), // Header: fixed height
Constraint::Fill(1), // Content: flexible
Constraint::Length(1), // Footer: fixed height
])
.areas(area);§Horizontal Sidebar Layout
use ratatui_core::layout::{Constraint, Layout, Rect};
let area = Rect::new(0, 0, 80, 24);
let [sidebar, main] = Layout::horizontal([
Constraint::Length(20), // Sidebar: fixed width
Constraint::Fill(1), // Main content: flexible
])
.areas(area);§Complex Nested Layout
use ratatui_core::layout::{Constraint, Layout, Rect};
fn create_complex_layout(area: Rect) -> [Rect; 4] {
// First, split vertically
let [header, body, footer] = Layout::vertical([
Constraint::Length(3), // Header
Constraint::Fill(1), // Body
Constraint::Length(1), // Footer
])
.areas(area);
// Then split the body horizontally
let [sidebar, main] = Layout::horizontal([
Constraint::Length(20), // Sidebar
Constraint::Fill(1), // Main
])
.areas(body);
[header, sidebar, main, footer]
}§Working with Constraints
Constraints define how space is allocated within a layout using the Cassowary constraint
solver algorithm. The constraint solver attempts to satisfy all constraints simultaneously,
with priorities determining which constraints take precedence when conflicts arise. Different
constraint types serve different purposes:
Constraint::Min- Minimum size constraintConstraint::Max- Maximum size constraintConstraint::Length- Fixed size in character cellsConstraint::Percentage- Relative size as a percentage of available spaceConstraint::Ratio- Proportional size using ratiosConstraint::Fill- Proportional fill of remaining space
Constraints are resolved in priority order, with Constraint::Min having the highest
priority and Constraint::Fill having the lowest. The constraint solver will satisfy as
many constraints as possible while respecting these priorities.
§Flexible Space Distribution
The Flex enum controls how extra space is distributed when constraints are satisfied:
Flex::Start- Align content to the start, leaving excess space at the endFlex::End- Align content to the end, leaving excess space at the startFlex::Center- Center content, distributing excess space equally on both sidesFlex::SpaceBetween- Distribute excess space evenly between elements, none at the endsFlex::SpaceAround- Distribute space around elements: equal padding on both sides of each element; gaps between elements are twice the edge spacingFlex::SpaceEvenly- Distribute space evenly: equal spacing between all elements, including before the first and after the last.Flex::Legacy- Legacy behavior (puts excess space in the last element)
§Positioning and Alignment
Use Position to represent specific points in the terminal, Size for dimensions, and the
alignment types for controlling content positioning within areas:
use ratatui_core::layout::{Alignment, Position, Rect, Size};
let pos = Position::new(10, 5);
let size = Size::new(80, 24);
let rect = Rect::new(pos.x, pos.y, size.width, size.height);
// Alignment for content within areas
let center = Alignment::Center;§Advanced Features
§Margins and Spacing
Add spacing around areas using uniform margins or between layout segments using Spacing:
use ratatui_core::layout::{Constraint, Layout, Margin, Rect, Spacing};
let layout = Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)])
.margin(2) // 2-cell margin on all sides
.spacing(Spacing::Space(1)); // 1-cell spacing between segments
// For asymmetric margins, use the Rect inner method directly
let area = Rect::new(0, 0, 80, 24).inner(Margin::new(2, 1));§Area Iteration
Iterate over rows, columns, or all positions within a rectangular area. The rows() and
columns() iterators return full Rect regions that can be used to render widgets or
passed to other layout methods for more complex nested layouts. The positions() iterator
returns Position values representing individual cell coordinates:
use ratatui_core::buffer::Buffer;
use ratatui_core::layout::{Constraint, Layout, Rect};
use ratatui_core::widgets::Widget;
let area = Rect::new(0, 0, 20, 10);
let mut buffer = Buffer::empty(area);
// Renders "Row 0", "Row 1", etc. in each horizontal row
for (i, row) in area.rows().enumerate() {
format!("Row {i}").render(row, &mut buffer);
}
// Renders column indices (0-9 repeating) in each vertical column
for (i, col) in area.columns().enumerate() {
format!("{}", i % 10).render(col, &mut buffer);
}
// Renders position indices (0-9 repeating) at each cell position
for (i, pos) in area.positions().enumerate() {
buffer[pos].set_symbol(&format!("{}", i % 10));
}§Performance Considerations
The layout system includes optional caching to improve performance for repeated layout
calculations. Layout caching is enabled by default in the main ratatui crate, but requires
explicitly enabling the layout-cache feature when using ratatui-core directly. When
enabled, layout results are cached based on the area and layout configuration.
§Related Documentation
For more detailed information and practical examples:
- Layout Concepts - Comprehensive guide to layout concepts
- Layout Recipes - Practical layout examples and patterns
- Grid Layout Recipe - Creating grid-based layouts
- Center a Widget Recipe - Centering content
- Dynamic Layouts Recipe - Creating responsive layouts
§Examples
See the Ratatui repository for complete examples:
constraints- Demonstrates different constraint typesflex- Shows flex space distributionlayout- Basic layout examples
Structs§
- Columns
- An iterator over columns within a
Rect. - Layout
- The primary layout engine for dividing terminal space using constraints and direction.
- Margin
- Represents spacing around rectangular areas.
- Offset
- Amounts by which to move a
Rect. - Position
- Position in the terminal coordinate system.
- Positions
- An iterator over positions within a
Rect. - Rect
- A rectangular area in the terminal.
- Rows
- An iterator over rows within a
Rect. - Size
- A simple size struct for representing dimensions in the terminal.
Enums§
- Constraint
- A constraint that defines the size of a layout element.
- Direction
- Defines the direction of a layout.
- Flex
- Defines the options for layout flex justify content in a container.
- Horizontal
Alignment - Horizontal content alignment within a layout area.
- Spacing
- Represents the spacing between segments in a layout.
- Vertical
Alignment - Vertical content alignment within a layout area.
Type Aliases§
- Alignment
- A type alias for
HorizontalAlignment.