0
# Layout and Navigation
1
2
This document covers Flet's layout system and navigation controls for organizing content and providing app navigation.
3
4
## Import
5
6
```python
7
import flet as ft
8
```
9
10
## Layout Controls
11
12
### Column
13
14
```python { .api }
15
class Column(Control):
16
"""Vertical layout container."""
17
18
def __init__(
19
self,
20
controls: List[Control] = None,
21
alignment: MainAxisAlignment = None,
22
horizontal_alignment: CrossAxisAlignment = None,
23
spacing: float = None,
24
tight: bool = None,
25
wrap: bool = None,
26
run_spacing: float = None,
27
scroll: ScrollMode = None,
28
auto_scroll: bool = None,
29
on_scroll_interval: int = None,
30
on_scroll: callable = None,
31
**kwargs
32
)
33
```
34
35
**Parameters:**
36
- `controls` (List[Control], optional): Child controls to layout vertically
37
- `alignment` (MainAxisAlignment, optional): Vertical alignment of children
38
- `horizontal_alignment` (CrossAxisAlignment, optional): Horizontal alignment of children
39
- `spacing` (float, optional): Vertical spacing between children
40
- `tight` (bool, optional): Whether to tightly fit children
41
- `wrap` (bool, optional): Whether to wrap children to new columns
42
- `scroll` (ScrollMode, optional): Scroll behavior (NONE, AUTO, ALWAYS, HIDDEN)
43
44
**Example:**
45
```python
46
ft.Column([
47
ft.Text("Item 1"),
48
ft.Text("Item 2"),
49
ft.Text("Item 3"),
50
],
51
alignment=ft.MainAxisAlignment.CENTER,
52
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
53
spacing=10)
54
```
55
56
### Row
57
58
```python { .api }
59
class Row(Control):
60
"""Horizontal layout container."""
61
62
def __init__(
63
self,
64
controls: List[Control] = None,
65
alignment: MainAxisAlignment = None,
66
vertical_alignment: CrossAxisAlignment = None,
67
spacing: float = None,
68
tight: bool = None,
69
wrap: bool = None,
70
run_spacing: float = None,
71
scroll: ScrollMode = None,
72
auto_scroll: bool = None,
73
on_scroll_interval: int = None,
74
on_scroll: callable = None,
75
**kwargs
76
)
77
```
78
79
**Parameters:**
80
- `controls` (List[Control], optional): Child controls to layout horizontally
81
- `alignment` (MainAxisAlignment, optional): Horizontal alignment of children
82
- `vertical_alignment` (CrossAxisAlignment, optional): Vertical alignment of children
83
- `spacing` (float, optional): Horizontal spacing between children
84
- `wrap` (bool, optional): Whether to wrap children to new rows
85
86
**Example:**
87
```python
88
ft.Row([
89
ft.Icon(ft.icons.STAR),
90
ft.Text("Favorite"),
91
ft.Switch()
92
],
93
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
94
vertical_alignment=ft.CrossAxisAlignment.CENTER)
95
```
96
97
### Container
98
99
```python { .api }
100
class Container(Control):
101
"""Single-child container with styling."""
102
103
def __init__(
104
self,
105
content: Control = None,
106
padding: PaddingValue = None,
107
margin: MarginValue = None,
108
alignment: Alignment = None,
109
bgcolor: str = None,
110
gradient: Gradient = None,
111
border: Border = None,
112
border_radius: BorderRadiusValue = None,
113
width: float = None,
114
height: float = None,
115
shadow: BoxShadow = None,
116
blur: Blur = None,
117
image_src: str = None,
118
image_src_base64: str = None,
119
image_fit: ImageFit = None,
120
image_repeat: ImageRepeat = None,
121
image_opacity: float = None,
122
shape: BoxShape = None,
123
clip_behavior: ClipBehavior = None,
124
ink: bool = None,
125
animate: AnimationValue = None,
126
tooltip: str = None,
127
on_click: callable = None,
128
on_long_press: callable = None,
129
on_hover: callable = None,
130
**kwargs
131
)
132
```
133
134
**Key Parameters:**
135
- `content` (Control, optional): Single child control
136
- `padding` (PaddingValue, optional): Internal padding
137
- `margin` (MarginValue, optional): External margin
138
- `alignment` (Alignment, optional): Child alignment within container
139
- `bgcolor` (str, optional): Background color
140
- `border` (Border, optional): Border styling
141
- `border_radius` (BorderRadiusValue, optional): Rounded corners
142
- `width` (float, optional): Container width
143
- `height` (float, optional): Container height
144
145
**Example:**
146
```python
147
ft.Container(
148
content=ft.Text("Hello, World!"),
149
padding=20,
150
margin=10,
151
bgcolor=ft.colors.BLUE_100,
152
border_radius=10,
153
alignment=ft.alignment.center
154
)
155
```
156
157
### Stack
158
159
```python { .api }
160
class Stack(Control):
161
"""Overlay layout container."""
162
163
def __init__(
164
self,
165
controls: List[Control] = None,
166
alignment: Alignment = None,
167
fit: StackFit = None,
168
clip_behavior: ClipBehavior = None,
169
**kwargs
170
)
171
```
172
173
**Parameters:**
174
- `controls` (List[Control], optional): Child controls to stack (later children on top)
175
- `alignment` (Alignment, optional): Default alignment for children
176
- `fit` (StackFit, optional): How to size the stack (LOOSE, EXPAND, PASS_THROUGH)
177
- `clip_behavior` (ClipBehavior, optional): Clipping behavior
178
179
**Example:**
180
```python
181
ft.Stack([
182
ft.Container(
183
width=200, height=200,
184
bgcolor=ft.colors.RED
185
),
186
ft.Positioned(
187
left=50, top=50,
188
child=ft.Container(
189
width=100, height=100,
190
bgcolor=ft.colors.BLUE
191
)
192
)
193
])
194
```
195
196
### Positioned
197
198
```python { .api }
199
class Positioned(Control):
200
"""Positioned child within a Stack."""
201
202
def __init__(
203
self,
204
left: float = None,
205
top: float = None,
206
right: float = None,
207
bottom: float = None,
208
width: float = None,
209
height: float = None,
210
child: Control = None,
211
**kwargs
212
)
213
```
214
215
### ResponsiveRow
216
217
```python { .api }
218
class ResponsiveRow(Control):
219
"""Responsive grid row layout."""
220
221
def __init__(
222
self,
223
controls: List[Control] = None,
224
alignment: MainAxisAlignment = None,
225
vertical_alignment: CrossAxisAlignment = None,
226
spacing: float = None,
227
run_spacing: float = None,
228
columns: int = 12,
229
**kwargs
230
)
231
```
232
233
**Parameters:**
234
- `controls` (List[Control], optional): Child controls with responsive column sizing
235
- `columns` (int, optional): Total columns in grid (default: 12)
236
- Each child control should have a `col` property defining responsive breakpoints
237
238
**Example:**
239
```python
240
ft.ResponsiveRow([
241
ft.Container(
242
ft.Text("25%"),
243
bgcolor=ft.colors.RED,
244
col={"sm": 6, "md": 4, "xl": 3}
245
),
246
ft.Container(
247
ft.Text("50%"),
248
bgcolor=ft.colors.GREEN,
249
col={"sm": 6, "md": 4, "xl": 6}
250
),
251
ft.Container(
252
ft.Text("25%"),
253
bgcolor=ft.colors.BLUE,
254
col={"sm": 12, "md": 4, "xl": 3}
255
)
256
])
257
```
258
259
### GridView
260
261
```python { .api }
262
class GridView(Control):
263
"""Scrollable grid layout."""
264
265
def __init__(
266
self,
267
controls: List[Control] = None,
268
horizontal: bool = None,
269
runs_count: int = None,
270
max_extent: float = None,
271
spacing: float = None,
272
run_spacing: float = None,
273
child_aspect_ratio: float = None,
274
padding: PaddingValue = None,
275
semantic_child_count: int = None,
276
cross_axis_count: int = None,
277
auto_scroll: bool = None,
278
reverse: bool = None,
279
on_scroll_interval: int = None,
280
on_scroll: callable = None,
281
**kwargs
282
)
283
```
284
285
**Parameters:**
286
- `controls` (List[Control], optional): Child controls to display in grid
287
- `runs_count` (int, optional): Number of columns/rows
288
- `max_extent` (float, optional): Maximum extent of each child
289
- `spacing` (float, optional): Spacing between children in main axis
290
- `run_spacing` (float, optional): Spacing between runs
291
- `child_aspect_ratio` (float, optional): Width/height ratio of children
292
293
### ListView
294
295
```python { .api }
296
class ListView(Control):
297
"""Scrollable list layout."""
298
299
def __init__(
300
self,
301
controls: List[Control] = None,
302
horizontal: bool = None,
303
spacing: float = None,
304
item_extent: float = None,
305
first_item_prototype: bool = None,
306
divider_thickness: float = None,
307
padding: PaddingValue = None,
308
auto_scroll: bool = None,
309
reverse: bool = None,
310
on_scroll_interval: int = None,
311
on_scroll: callable = None,
312
**kwargs
313
)
314
```
315
316
**Example:**
317
```python
318
ft.ListView([
319
ft.ListTile(title=ft.Text(f"Item {i}")) for i in range(100)
320
],
321
spacing=10,
322
padding=20)
323
```
324
325
### SafeArea
326
327
```python { .api }
328
class SafeArea(Control):
329
"""Safe area container that avoids system intrusions."""
330
331
def __init__(
332
self,
333
content: Control = None,
334
left: bool = True,
335
top: bool = True,
336
right: bool = True,
337
bottom: bool = True,
338
maintain_bottom_view_padding: bool = None,
339
minimum: PaddingValue = None,
340
**kwargs
341
)
342
```
343
344
## Navigation Controls
345
346
### AppBar
347
348
```python { .api }
349
class AppBar(Control):
350
"""Application bar (top navigation)."""
351
352
def __init__(
353
self,
354
leading: Control = None,
355
leading_width: float = None,
356
automatically_imply_leading: bool = None,
357
title: Control = None,
358
center_title: bool = None,
359
actions: List[Control] = None,
360
elevation: float = None,
361
shadow_color: str = None,
362
surface_tint_color: str = None,
363
shape: OutlinedBorder = None,
364
bgcolor: str = None,
365
foreground_color: str = None,
366
exclude_header_semantics: bool = None,
367
title_spacing: float = None,
368
toolbar_height: float = None,
369
toolbar_opacity: float = None,
370
toolbar_text_style: TextStyle = None,
371
title_text_style: TextStyle = None,
372
**kwargs
373
)
374
```
375
376
**Parameters:**
377
- `leading` (Control, optional): Widget displayed before the title (back button, menu icon)
378
- `title` (Control, optional): Primary title widget
379
- `center_title` (bool, optional): Whether to center the title
380
- `actions` (List[Control], optional): Action buttons displayed after title
381
- `elevation` (float, optional): AppBar shadow elevation
382
- `bgcolor` (str, optional): Background color
383
384
**Example:**
385
```python
386
ft.AppBar(
387
leading=ft.Icon(ft.icons.MENU),
388
title=ft.Text("My App"),
389
center_title=True,
390
bgcolor=ft.colors.SURFACE_VARIANT,
391
actions=[
392
ft.IconButton(ft.icons.SEARCH),
393
ft.IconButton(ft.icons.MORE_VERT)
394
]
395
)
396
```
397
398
### BottomAppBar
399
400
```python { .api }
401
class BottomAppBar(Control):
402
"""Bottom application bar."""
403
404
def __init__(
405
self,
406
content: Control = None,
407
bgcolor: str = None,
408
surface_tint_color: str = None,
409
shadow_color: str = None,
410
elevation: float = None,
411
height: float = None,
412
shape: NotchedShape = None,
413
clip_behavior: ClipBehavior = None,
414
notch_margin: float = None,
415
padding: PaddingValue = None,
416
**kwargs
417
)
418
```
419
420
### NavigationBar
421
422
```python { .api }
423
class NavigationBar(Control):
424
"""Bottom navigation bar with destinations."""
425
426
def __init__(
427
self,
428
destinations: List[NavigationDestination] = None,
429
selected_index: int = 0,
430
bgcolor: str = None,
431
surface_tint_color: str = None,
432
elevation: float = None,
433
shadow_color: str = None,
434
indicator_color: str = None,
435
indicator_shape: OutlinedBorder = None,
436
height: float = None,
437
label_behavior: NavigationBarLabelBehavior = None,
438
overlay_color: str = None,
439
animation_duration: int = None,
440
on_change: callable = None,
441
**kwargs
442
)
443
```
444
445
**Parameters:**
446
- `destinations` (List[NavigationDestination], optional): Navigation destinations
447
- `selected_index` (int, optional): Currently selected destination index
448
- `on_change` (callable, optional): Callback for destination changes
449
450
**Example:**
451
```python
452
def route_change(e):
453
index = e.control.selected_index
454
# Handle navigation based on index
455
456
ft.NavigationBar(
457
destinations=[
458
ft.NavigationDestination(icon=ft.icons.HOME, label="Home"),
459
ft.NavigationDestination(icon=ft.icons.SEARCH, label="Search"),
460
ft.NavigationDestination(icon=ft.icons.PERSON, label="Profile")
461
],
462
on_change=route_change
463
)
464
```
465
466
### NavigationDestination
467
468
```python { .api }
469
class NavigationDestination(Control):
470
"""Navigation bar destination."""
471
472
def __init__(
473
self,
474
icon: str = None,
475
icon_content: Control = None,
476
selected_icon: str = None,
477
selected_icon_content: Control = None,
478
label: str = None,
479
tooltip: str = None,
480
**kwargs
481
)
482
```
483
484
### NavigationRail
485
486
```python { .api }
487
class NavigationRail(Control):
488
"""Side navigation rail."""
489
490
def __init__(
491
self,
492
destinations: List[NavigationRailDestination] = None,
493
selected_index: int = None,
494
extended: bool = None,
495
leading: Control = None,
496
trailing: Control = None,
497
min_width: float = None,
498
min_extended_width: float = None,
499
group_alignment: float = None,
500
label_type: NavigationRailLabelType = None,
501
bgcolor: str = None,
502
elevation: float = None,
503
indicator_color: str = None,
504
indicator_shape: OutlinedBorder = None,
505
on_change: callable = None,
506
**kwargs
507
)
508
```
509
510
### NavigationDrawer
511
512
```python { .api }
513
class NavigationDrawer(Control):
514
"""Navigation drawer (side menu)."""
515
516
def __init__(
517
self,
518
controls: List[Control] = None,
519
selected_index: int = None,
520
bgcolor: str = None,
521
shadow_color: str = None,
522
surface_tint_color: str = None,
523
elevation: float = None,
524
indicator_color: str = None,
525
indicator_shape: OutlinedBorder = None,
526
position: NavigationDrawerPosition = None,
527
tile_padding: PaddingValue = None,
528
on_change: callable = None,
529
**kwargs
530
)
531
```
532
533
### Tabs
534
535
```python { .api }
536
class Tabs(Control):
537
"""Tab container with multiple tabs."""
538
539
def __init__(
540
self,
541
tabs: List[Tab] = None,
542
selected_index: int = 0,
543
animation_duration: int = None,
544
tab_alignment: TabAlignment = None,
545
is_secondary: bool = None,
546
indicator_border_radius: BorderRadiusValue = None,
547
indicator_border_side: BorderSide = None,
548
indicator_color: str = None,
549
indicator_padding: PaddingValue = None,
550
indicator_tab_size: bool = None,
551
divider_color: str = None,
552
divider_height: float = None,
553
label_color: str = None,
554
label_padding: PaddingValue = None,
555
mouse_cursor: MouseCursor = None,
556
overlay_color: str = None,
557
physics: ScrollPhysics = None,
558
splash_border_radius: BorderRadiusValue = None,
559
tab_flex: int = None,
560
unselected_label_color: str = None,
561
scrollable: bool = None,
562
on_change: callable = None,
563
**kwargs
564
)
565
```
566
567
**Parameters:**
568
- `tabs` (List[Tab], optional): List of tab definitions
569
- `selected_index` (int, optional): Currently selected tab index
570
- `scrollable` (bool, optional): Whether tabs can scroll horizontally
571
- `on_change` (callable, optional): Callback for tab changes
572
573
### Tab
574
575
```python { .api }
576
class Tab(Control):
577
"""Individual tab definition."""
578
579
def __init__(
580
self,
581
text: str = None,
582
content: Control = None,
583
icon: str = None,
584
tab_content: Control = None,
585
**kwargs
586
)
587
```
588
589
**Example:**
590
```python
591
ft.Tabs(
592
tabs=[
593
ft.Tab(
594
text="Home",
595
icon=ft.icons.HOME,
596
content=ft.Text("Home content")
597
),
598
ft.Tab(
599
text="Settings",
600
icon=ft.icons.SETTINGS,
601
content=ft.Text("Settings content")
602
)
603
],
604
selected_index=0
605
)
606
```
607
608
### MenuBar
609
610
```python { .api }
611
class MenuBar(Control):
612
"""Menu bar with dropdown menus."""
613
614
def __init__(
615
self,
616
controls: List[Control] = None,
617
style: MenuStyle = None,
618
clip_behavior: ClipBehavior = None,
619
**kwargs
620
)
621
```
622
623
### MenuItemButton
624
625
```python { .api }
626
class MenuItemButton(Control):
627
"""Menu item button."""
628
629
def __init__(
630
self,
631
content: Control = None,
632
leading_icon: str = None,
633
trailing_icon: str = None,
634
style: ButtonStyle = None,
635
close_on_click: bool = True,
636
on_click: callable = None,
637
on_hover: callable = None,
638
on_focus: callable = None,
639
**kwargs
640
)
641
```
642
643
### SubmenuButton
644
645
```python { .api }
646
class SubmenuButton(Control):
647
"""Submenu button with nested menu items."""
648
649
def __init__(
650
self,
651
content: Control = None,
652
leading_icon: str = None,
653
trailing_icon: str = None,
654
controls: List[Control] = None,
655
style: ButtonStyle = None,
656
align_on_right: bool = None,
657
clip_behavior: ClipBehavior = None,
658
menu_style: MenuStyle = None,
659
on_open: callable = None,
660
on_close: callable = None,
661
on_hover: callable = None,
662
on_focus: callable = None,
663
**kwargs
664
)
665
```
666
667
## Cupertino (iOS-Style) Navigation
668
669
### CupertinoAppBar
670
671
```python { .api }
672
class CupertinoAppBar(Control):
673
"""iOS-style app bar."""
674
675
def __init__(
676
self,
677
leading: Control = None,
678
automatically_imply_leading: bool = True,
679
automatically_imply_middle: bool = True,
680
previous_page_title: str = None,
681
middle: Control = None,
682
trailing: Control = None,
683
border: Border = None,
684
bgcolor: str = None,
685
padding: PaddingValue = None,
686
**kwargs
687
)
688
```
689
690
### CupertinoNavigationBar
691
692
```python { .api }
693
class CupertinoNavigationBar(Control):
694
"""iOS-style navigation bar."""
695
696
def __init__(
697
self,
698
destinations: List[CupertinoNavigationDestination] = None,
699
selected_index: int = 0,
700
bgcolor: str = None,
701
inactive_color: str = None,
702
active_color: str = None,
703
border: Border = None,
704
height: float = None,
705
on_change: callable = None,
706
**kwargs
707
)
708
```
709
710
## Layout Best Practices
711
712
### Responsive Design Patterns
713
714
```python
715
# Mobile-first responsive layout
716
def build_responsive_layout():
717
return ft.ResponsiveRow([
718
ft.Container(
719
ft.Text("Sidebar"),
720
bgcolor=ft.colors.BLUE_100,
721
col={"xs": 12, "sm": 12, "md": 3, "lg": 2}
722
),
723
ft.Container(
724
ft.Text("Main Content"),
725
bgcolor=ft.colors.GREEN_100,
726
col={"xs": 12, "sm": 12, "md": 9, "lg": 10}
727
)
728
])
729
```
730
731
### Nested Layouts
732
733
```python
734
# Complex layout composition
735
def build_complex_layout():
736
return ft.Column([
737
# Header
738
ft.Container(
739
ft.Text("Header"),
740
height=60,
741
bgcolor=ft.colors.BLUE
742
),
743
744
# Body with sidebar and content
745
ft.Expanded(
746
ft.Row([
747
# Sidebar
748
ft.Container(
749
ft.Column([
750
ft.Text("Menu Item 1"),
751
ft.Text("Menu Item 2")
752
]),
753
width=200,
754
bgcolor=ft.colors.GREY_100
755
),
756
757
# Main content
758
ft.Expanded(
759
ft.Container(
760
ft.Text("Main Content"),
761
bgcolor=ft.colors.WHITE
762
)
763
)
764
])
765
),
766
767
# Footer
768
ft.Container(
769
ft.Text("Footer"),
770
height=40,
771
bgcolor=ft.colors.BLUE
772
)
773
])
774
```
775
776
### Navigation Patterns
777
778
```python
779
# Tab-based navigation
780
class TabApp:
781
def __init__(self):
782
self.selected_tab = 0
783
784
def tab_changed(self, e):
785
self.selected_tab = e.control.selected_index
786
# Update content based on selected tab
787
788
def build(self):
789
return ft.Column([
790
ft.Tabs(
791
selected_index=self.selected_tab,
792
on_change=self.tab_changed,
793
tabs=[
794
ft.Tab(text="Home", content=self.build_home()),
795
ft.Tab(text="Profile", content=self.build_profile()),
796
ft.Tab(text="Settings", content=self.build_settings())
797
]
798
)
799
])
800
801
# Navigation rail pattern
802
def build_navigation_rail_layout():
803
return ft.Row([
804
ft.NavigationRail(
805
destinations=[
806
ft.NavigationRailDestination(
807
icon=ft.icons.HOME,
808
label="Home"
809
),
810
ft.NavigationRailDestination(
811
icon=ft.icons.SEARCH,
812
label="Search"
813
)
814
],
815
on_change=lambda e: handle_navigation(e.control.selected_index)
816
),
817
ft.VerticalDivider(width=1),
818
ft.Expanded(
819
# Main content area
820
ft.Container(ft.Text("Content Area"))
821
)
822
])
823
```
824
825
### Scrollable Layouts
826
827
```python
828
# Infinite scroll list
829
def build_infinite_scroll():
830
items = [ft.ListTile(title=ft.Text(f"Item {i}")) for i in range(1000)]
831
832
return ft.ListView(
833
controls=items,
834
spacing=0,
835
padding=ft.padding.all(16),
836
auto_scroll=True
837
)
838
839
# Custom scroll behavior
840
def build_custom_scroll():
841
return ft.Column([
842
ft.Container(
843
ft.ListView([
844
ft.Text(f"Scrollable item {i}") for i in range(50)
845
]),
846
height=300,
847
border=ft.border.all(1, ft.colors.GREY)
848
)
849
])
850
```
851
852
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.