Skip to main content

Module layout

Module layout 

Source
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 direction
  • Rect - Represents a rectangular area with position and dimensions
  • Constraint - 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 system
  • Size - Represents dimensions (width and height)
  • Margin - Defines spacing around rectangular areas
  • Offset - Represents relative movement in the coordinate system
  • Spacing - Controls spacing or overlap between layout segments

§Alignment

§Iteration Support

  • Rows - Iterator over horizontal rows within a rectangular area
  • Columns - Iterator over vertical columns within a rectangular area
  • Positions - 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 bottom

Note: 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:

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 end
  • Flex::End - Align content to the end, leaving excess space at the start
  • Flex::Center - Center content, distributing excess space equally on both sides
  • Flex::SpaceBetween - Distribute excess space evenly between elements, none at the ends
  • Flex::SpaceAround - Distribute space around elements: equal padding on both sides of each element; gaps between elements are twice the edge spacing
  • Flex::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.

For more detailed information and practical examples:

§Examples

See the Ratatui repository for complete examples:

  • constraints - Demonstrates different constraint types
  • flex - Shows flex space distribution
  • layout - 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.
HorizontalAlignment
Horizontal content alignment within a layout area.
Spacing
Represents the spacing between segments in a layout.
VerticalAlignment
Vertical content alignment within a layout area.

Type Aliases§

Alignment
A type alias for HorizontalAlignment.