Skip to content

How to Center Widgets

Problem

You want to center a widget within some area of your TUI’s layout.

Solution

To center a widget in any area, create a Rect that is centered within the area. You can calculate the x and y positions of the widget by subtracting the widget width and height from the enclosing area’s width and height, respectively, and dividing by 2.

More simply, you can use the Layout struct to center a widget. You can use a Horizontal layout followed by a Vertical layout to get a centered Rect. The Flex enum can be used to specify the alignment of the rect within the containing area.

Centering horizontally

use ratatui::layout::{Constraint, Flex, Layout, Rect};
fn center_horizontal(area: Rect, width: u16) -> Rect {
let [area] = Layout::horizontal([Constraint::Length(width)])
.flex(Flex::Center)
.areas(area);
area
}

Centering vertically

use ratatui::layout::{Constraint, Flex, Layout, Rect};
fn center_vertical(area: Rect, height: u16) -> Rect {
let [area] = Layout::vertical([Constraint::Length(height)])
.flex(Flex::Center)
.areas(area);
area
}

Centering both horizontally and vertically

You can use a Vertical layout followed by a Horizontal layout to get a centered Rect. This example centers the Rect using constraints on each axis. This lets you allocate the space available based on a percentage, ratio, or fixed size.

13 collapsed lines
/// Centers a [`Rect`] within another [`Rect`] using the provided [`Constraint`]s.
///
/// # Examples
///
/// ```rust
/// use ratatui::layout::{Constraint, Rect};
///
/// let area = Rect::new(0, 0, 100, 100);
/// let horizontal = Constraint::Percentage(20);
/// let vertical = Constraint::Percentage(30);
///
/// let centered = center(area, horizontal, vertical);
/// ```
fn center(area: Rect, horizontal: Constraint, vertical: Constraint) -> Rect {
let [area] = Layout::horizontal([horizontal])
.flex(Flex::Center)
.areas(area);
let [area] = Layout::vertical([vertical]).flex(Flex::Center).areas(area);
area
}

Centering a widget

You can use these methods to draw any widget centered on the containing area.

fn render(frame: &mut Frame) {
let text = Text::raw("Hello world!");
let area = center(
frame.area(),
Constraint::Length(text.width() as u16),
Constraint::Length(1),
);
frame.render_widget(text, area);
}

Popups

A common use case for this feature is to create a popup style dialog block. For this, typically, you’ll want to use the [Clear] widget to clear the popup area before rendering your content to it. The following is an example of how you might do that:

fn render_popup(frame: &mut Frame) {
let area = center(
frame.area(),
Constraint::Percentage(20),
Constraint::Length(3), // top and bottom border + content
);
let popup = Paragraph::new("Popup content").block(Block::bordered().title("Popup"));
frame.render_widget(Clear, area);
frame.render_widget(popup, area);
}

Summary

The Layout struct provides a simple way to center a widget in a terminal. You can use the Horizontal and Vertical layouts to center a widget on the x and y axes, respectively. You can also use the Flex enum to specify the alignment of the widget within the containing area. There are more advanced layout options available in the Layout struct but not covered in this recipe, which you can use to create more complex layouts.

Full code for this recipe is available in the website repo at: https://github.com/ratatui/ratatui-website/blob/main/code/recipes/src/layout.rs

See also

There are several third party widget libraries for making popups easy to use: