Flet is a rich User Interface framework to quickly build interactive web, desktop and mobile apps in Python without prior knowledge of web technologies.
—
This document covers Flet's layout system and navigation controls for organizing content and providing app navigation.
import flet as ftclass Column(Control):
"""Vertical layout container."""
def __init__(
self,
controls: List[Control] = None,
alignment: MainAxisAlignment = None,
horizontal_alignment: CrossAxisAlignment = None,
spacing: float = None,
tight: bool = None,
wrap: bool = None,
run_spacing: float = None,
scroll: ScrollMode = None,
auto_scroll: bool = None,
on_scroll_interval: int = None,
on_scroll: callable = None,
**kwargs
)Parameters:
controls (List[Control], optional): Child controls to layout verticallyalignment (MainAxisAlignment, optional): Vertical alignment of childrenhorizontal_alignment (CrossAxisAlignment, optional): Horizontal alignment of childrenspacing (float, optional): Vertical spacing between childrentight (bool, optional): Whether to tightly fit childrenwrap (bool, optional): Whether to wrap children to new columnsscroll (ScrollMode, optional): Scroll behavior (NONE, AUTO, ALWAYS, HIDDEN)Example:
ft.Column([
ft.Text("Item 1"),
ft.Text("Item 2"),
ft.Text("Item 3"),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=10)class Row(Control):
"""Horizontal layout container."""
def __init__(
self,
controls: List[Control] = None,
alignment: MainAxisAlignment = None,
vertical_alignment: CrossAxisAlignment = None,
spacing: float = None,
tight: bool = None,
wrap: bool = None,
run_spacing: float = None,
scroll: ScrollMode = None,
auto_scroll: bool = None,
on_scroll_interval: int = None,
on_scroll: callable = None,
**kwargs
)Parameters:
controls (List[Control], optional): Child controls to layout horizontallyalignment (MainAxisAlignment, optional): Horizontal alignment of childrenvertical_alignment (CrossAxisAlignment, optional): Vertical alignment of childrenspacing (float, optional): Horizontal spacing between childrenwrap (bool, optional): Whether to wrap children to new rowsExample:
ft.Row([
ft.Icon(ft.icons.STAR),
ft.Text("Favorite"),
ft.Switch()
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
vertical_alignment=ft.CrossAxisAlignment.CENTER)class Container(Control):
"""Single-child container with styling."""
def __init__(
self,
content: Control = None,
padding: PaddingValue = None,
margin: MarginValue = None,
alignment: Alignment = None,
bgcolor: str = None,
gradient: Gradient = None,
border: Border = None,
border_radius: BorderRadiusValue = None,
width: float = None,
height: float = None,
shadow: BoxShadow = None,
blur: Blur = None,
image_src: str = None,
image_src_base64: str = None,
image_fit: ImageFit = None,
image_repeat: ImageRepeat = None,
image_opacity: float = None,
shape: BoxShape = None,
clip_behavior: ClipBehavior = None,
ink: bool = None,
animate: AnimationValue = None,
tooltip: str = None,
on_click: callable = None,
on_long_press: callable = None,
on_hover: callable = None,
**kwargs
)Key Parameters:
content (Control, optional): Single child controlpadding (PaddingValue, optional): Internal paddingmargin (MarginValue, optional): External marginalignment (Alignment, optional): Child alignment within containerbgcolor (str, optional): Background colorborder (Border, optional): Border stylingborder_radius (BorderRadiusValue, optional): Rounded cornerswidth (float, optional): Container widthheight (float, optional): Container heightExample:
ft.Container(
content=ft.Text("Hello, World!"),
padding=20,
margin=10,
bgcolor=ft.colors.BLUE_100,
border_radius=10,
alignment=ft.alignment.center
)class Stack(Control):
"""Overlay layout container."""
def __init__(
self,
controls: List[Control] = None,
alignment: Alignment = None,
fit: StackFit = None,
clip_behavior: ClipBehavior = None,
**kwargs
)Parameters:
controls (List[Control], optional): Child controls to stack (later children on top)alignment (Alignment, optional): Default alignment for childrenfit (StackFit, optional): How to size the stack (LOOSE, EXPAND, PASS_THROUGH)clip_behavior (ClipBehavior, optional): Clipping behaviorExample:
ft.Stack([
ft.Container(
width=200, height=200,
bgcolor=ft.colors.RED
),
ft.Positioned(
left=50, top=50,
child=ft.Container(
width=100, height=100,
bgcolor=ft.colors.BLUE
)
)
])class Positioned(Control):
"""Positioned child within a Stack."""
def __init__(
self,
left: float = None,
top: float = None,
right: float = None,
bottom: float = None,
width: float = None,
height: float = None,
child: Control = None,
**kwargs
)class ResponsiveRow(Control):
"""Responsive grid row layout."""
def __init__(
self,
controls: List[Control] = None,
alignment: MainAxisAlignment = None,
vertical_alignment: CrossAxisAlignment = None,
spacing: float = None,
run_spacing: float = None,
columns: int = 12,
**kwargs
)Parameters:
controls (List[Control], optional): Child controls with responsive column sizingcolumns (int, optional): Total columns in grid (default: 12)col property defining responsive breakpointsExample:
ft.ResponsiveRow([
ft.Container(
ft.Text("25%"),
bgcolor=ft.colors.RED,
col={"sm": 6, "md": 4, "xl": 3}
),
ft.Container(
ft.Text("50%"),
bgcolor=ft.colors.GREEN,
col={"sm": 6, "md": 4, "xl": 6}
),
ft.Container(
ft.Text("25%"),
bgcolor=ft.colors.BLUE,
col={"sm": 12, "md": 4, "xl": 3}
)
])class GridView(Control):
"""Scrollable grid layout."""
def __init__(
self,
controls: List[Control] = None,
horizontal: bool = None,
runs_count: int = None,
max_extent: float = None,
spacing: float = None,
run_spacing: float = None,
child_aspect_ratio: float = None,
padding: PaddingValue = None,
semantic_child_count: int = None,
cross_axis_count: int = None,
auto_scroll: bool = None,
reverse: bool = None,
on_scroll_interval: int = None,
on_scroll: callable = None,
**kwargs
)Parameters:
controls (List[Control], optional): Child controls to display in gridruns_count (int, optional): Number of columns/rowsmax_extent (float, optional): Maximum extent of each childspacing (float, optional): Spacing between children in main axisrun_spacing (float, optional): Spacing between runschild_aspect_ratio (float, optional): Width/height ratio of childrenclass ListView(Control):
"""Scrollable list layout."""
def __init__(
self,
controls: List[Control] = None,
horizontal: bool = None,
spacing: float = None,
item_extent: float = None,
first_item_prototype: bool = None,
divider_thickness: float = None,
padding: PaddingValue = None,
auto_scroll: bool = None,
reverse: bool = None,
on_scroll_interval: int = None,
on_scroll: callable = None,
**kwargs
)Example:
ft.ListView([
ft.ListTile(title=ft.Text(f"Item {i}")) for i in range(100)
],
spacing=10,
padding=20)class SafeArea(Control):
"""Safe area container that avoids system intrusions."""
def __init__(
self,
content: Control = None,
left: bool = True,
top: bool = True,
right: bool = True,
bottom: bool = True,
maintain_bottom_view_padding: bool = None,
minimum: PaddingValue = None,
**kwargs
)class AppBar(Control):
"""Application bar (top navigation)."""
def __init__(
self,
leading: Control = None,
leading_width: float = None,
automatically_imply_leading: bool = None,
title: Control = None,
center_title: bool = None,
actions: List[Control] = None,
elevation: float = None,
shadow_color: str = None,
surface_tint_color: str = None,
shape: OutlinedBorder = None,
bgcolor: str = None,
foreground_color: str = None,
exclude_header_semantics: bool = None,
title_spacing: float = None,
toolbar_height: float = None,
toolbar_opacity: float = None,
toolbar_text_style: TextStyle = None,
title_text_style: TextStyle = None,
**kwargs
)Parameters:
leading (Control, optional): Widget displayed before the title (back button, menu icon)title (Control, optional): Primary title widgetcenter_title (bool, optional): Whether to center the titleactions (List[Control], optional): Action buttons displayed after titleelevation (float, optional): AppBar shadow elevationbgcolor (str, optional): Background colorExample:
ft.AppBar(
leading=ft.Icon(ft.icons.MENU),
title=ft.Text("My App"),
center_title=True,
bgcolor=ft.colors.SURFACE_VARIANT,
actions=[
ft.IconButton(ft.icons.SEARCH),
ft.IconButton(ft.icons.MORE_VERT)
]
)class BottomAppBar(Control):
"""Bottom application bar."""
def __init__(
self,
content: Control = None,
bgcolor: str = None,
surface_tint_color: str = None,
shadow_color: str = None,
elevation: float = None,
height: float = None,
shape: NotchedShape = None,
clip_behavior: ClipBehavior = None,
notch_margin: float = None,
padding: PaddingValue = None,
**kwargs
)class NavigationBar(Control):
"""Bottom navigation bar with destinations."""
def __init__(
self,
destinations: List[NavigationDestination] = None,
selected_index: int = 0,
bgcolor: str = None,
surface_tint_color: str = None,
elevation: float = None,
shadow_color: str = None,
indicator_color: str = None,
indicator_shape: OutlinedBorder = None,
height: float = None,
label_behavior: NavigationBarLabelBehavior = None,
overlay_color: str = None,
animation_duration: int = None,
on_change: callable = None,
**kwargs
)Parameters:
destinations (List[NavigationDestination], optional): Navigation destinationsselected_index (int, optional): Currently selected destination indexon_change (callable, optional): Callback for destination changesExample:
def route_change(e):
index = e.control.selected_index
# Handle navigation based on index
ft.NavigationBar(
destinations=[
ft.NavigationDestination(icon=ft.icons.HOME, label="Home"),
ft.NavigationDestination(icon=ft.icons.SEARCH, label="Search"),
ft.NavigationDestination(icon=ft.icons.PERSON, label="Profile")
],
on_change=route_change
)class NavigationDestination(Control):
"""Navigation bar destination."""
def __init__(
self,
icon: str = None,
icon_content: Control = None,
selected_icon: str = None,
selected_icon_content: Control = None,
label: str = None,
tooltip: str = None,
**kwargs
)class NavigationRail(Control):
"""Side navigation rail."""
def __init__(
self,
destinations: List[NavigationRailDestination] = None,
selected_index: int = None,
extended: bool = None,
leading: Control = None,
trailing: Control = None,
min_width: float = None,
min_extended_width: float = None,
group_alignment: float = None,
label_type: NavigationRailLabelType = None,
bgcolor: str = None,
elevation: float = None,
indicator_color: str = None,
indicator_shape: OutlinedBorder = None,
on_change: callable = None,
**kwargs
)class NavigationDrawer(Control):
"""Navigation drawer (side menu)."""
def __init__(
self,
controls: List[Control] = None,
selected_index: int = None,
bgcolor: str = None,
shadow_color: str = None,
surface_tint_color: str = None,
elevation: float = None,
indicator_color: str = None,
indicator_shape: OutlinedBorder = None,
position: NavigationDrawerPosition = None,
tile_padding: PaddingValue = None,
on_change: callable = None,
**kwargs
)class Tabs(Control):
"""Tab container with multiple tabs."""
def __init__(
self,
tabs: List[Tab] = None,
selected_index: int = 0,
animation_duration: int = None,
tab_alignment: TabAlignment = None,
is_secondary: bool = None,
indicator_border_radius: BorderRadiusValue = None,
indicator_border_side: BorderSide = None,
indicator_color: str = None,
indicator_padding: PaddingValue = None,
indicator_tab_size: bool = None,
divider_color: str = None,
divider_height: float = None,
label_color: str = None,
label_padding: PaddingValue = None,
mouse_cursor: MouseCursor = None,
overlay_color: str = None,
physics: ScrollPhysics = None,
splash_border_radius: BorderRadiusValue = None,
tab_flex: int = None,
unselected_label_color: str = None,
scrollable: bool = None,
on_change: callable = None,
**kwargs
)Parameters:
tabs (List[Tab], optional): List of tab definitionsselected_index (int, optional): Currently selected tab indexscrollable (bool, optional): Whether tabs can scroll horizontallyon_change (callable, optional): Callback for tab changesclass Tab(Control):
"""Individual tab definition."""
def __init__(
self,
text: str = None,
content: Control = None,
icon: str = None,
tab_content: Control = None,
**kwargs
)Example:
ft.Tabs(
tabs=[
ft.Tab(
text="Home",
icon=ft.icons.HOME,
content=ft.Text("Home content")
),
ft.Tab(
text="Settings",
icon=ft.icons.SETTINGS,
content=ft.Text("Settings content")
)
],
selected_index=0
)class MenuBar(Control):
"""Menu bar with dropdown menus."""
def __init__(
self,
controls: List[Control] = None,
style: MenuStyle = None,
clip_behavior: ClipBehavior = None,
**kwargs
)class MenuItemButton(Control):
"""Menu item button."""
def __init__(
self,
content: Control = None,
leading_icon: str = None,
trailing_icon: str = None,
style: ButtonStyle = None,
close_on_click: bool = True,
on_click: callable = None,
on_hover: callable = None,
on_focus: callable = None,
**kwargs
)class SubmenuButton(Control):
"""Submenu button with nested menu items."""
def __init__(
self,
content: Control = None,
leading_icon: str = None,
trailing_icon: str = None,
controls: List[Control] = None,
style: ButtonStyle = None,
align_on_right: bool = None,
clip_behavior: ClipBehavior = None,
menu_style: MenuStyle = None,
on_open: callable = None,
on_close: callable = None,
on_hover: callable = None,
on_focus: callable = None,
**kwargs
)class CupertinoAppBar(Control):
"""iOS-style app bar."""
def __init__(
self,
leading: Control = None,
automatically_imply_leading: bool = True,
automatically_imply_middle: bool = True,
previous_page_title: str = None,
middle: Control = None,
trailing: Control = None,
border: Border = None,
bgcolor: str = None,
padding: PaddingValue = None,
**kwargs
)class CupertinoNavigationBar(Control):
"""iOS-style navigation bar."""
def __init__(
self,
destinations: List[CupertinoNavigationDestination] = None,
selected_index: int = 0,
bgcolor: str = None,
inactive_color: str = None,
active_color: str = None,
border: Border = None,
height: float = None,
on_change: callable = None,
**kwargs
)# Mobile-first responsive layout
def build_responsive_layout():
return ft.ResponsiveRow([
ft.Container(
ft.Text("Sidebar"),
bgcolor=ft.colors.BLUE_100,
col={"xs": 12, "sm": 12, "md": 3, "lg": 2}
),
ft.Container(
ft.Text("Main Content"),
bgcolor=ft.colors.GREEN_100,
col={"xs": 12, "sm": 12, "md": 9, "lg": 10}
)
])# Complex layout composition
def build_complex_layout():
return ft.Column([
# Header
ft.Container(
ft.Text("Header"),
height=60,
bgcolor=ft.colors.BLUE
),
# Body with sidebar and content
ft.Expanded(
ft.Row([
# Sidebar
ft.Container(
ft.Column([
ft.Text("Menu Item 1"),
ft.Text("Menu Item 2")
]),
width=200,
bgcolor=ft.colors.GREY_100
),
# Main content
ft.Expanded(
ft.Container(
ft.Text("Main Content"),
bgcolor=ft.colors.WHITE
)
)
])
),
# Footer
ft.Container(
ft.Text("Footer"),
height=40,
bgcolor=ft.colors.BLUE
)
])# Tab-based navigation
class TabApp:
def __init__(self):
self.selected_tab = 0
def tab_changed(self, e):
self.selected_tab = e.control.selected_index
# Update content based on selected tab
def build(self):
return ft.Column([
ft.Tabs(
selected_index=self.selected_tab,
on_change=self.tab_changed,
tabs=[
ft.Tab(text="Home", content=self.build_home()),
ft.Tab(text="Profile", content=self.build_profile()),
ft.Tab(text="Settings", content=self.build_settings())
]
)
])
# Navigation rail pattern
def build_navigation_rail_layout():
return ft.Row([
ft.NavigationRail(
destinations=[
ft.NavigationRailDestination(
icon=ft.icons.HOME,
label="Home"
),
ft.NavigationRailDestination(
icon=ft.icons.SEARCH,
label="Search"
)
],
on_change=lambda e: handle_navigation(e.control.selected_index)
),
ft.VerticalDivider(width=1),
ft.Expanded(
# Main content area
ft.Container(ft.Text("Content Area"))
)
])# Infinite scroll list
def build_infinite_scroll():
items = [ft.ListTile(title=ft.Text(f"Item {i}")) for i in range(1000)]
return ft.ListView(
controls=items,
spacing=0,
padding=ft.padding.all(16),
auto_scroll=True
)
# Custom scroll behavior
def build_custom_scroll():
return ft.Column([
ft.Container(
ft.ListView([
ft.Text(f"Scrollable item {i}") for i in range(50)
]),
height=300,
border=ft.border.all(1, ft.colors.GREY)
)
])This covers the comprehensive layout and navigation system in Flet, enabling you to create sophisticated, responsive user interfaces with proper navigation patterns for any type of application.
Install with Tessl CLI
npx tessl i tessl/pypi-flet