The Column control in Flet is a powerful widget that allows you to arrange its child elements in a vertical layout. It provides a flexible and intuitive way to manage UI elements, ensuring proper alignment, spacing, wrapping, and scrolling capabilities.

Expanding Child Controls

To make a child control expand and fill the available vertical space, set its expand property. This is useful when designing dynamic layouts that adjust based on available screen space.

Examples

Column Spacing

The following example demonstrates how to control the spacing between child elements in a Column:

import flet as ft

def main(page: ft.Page):
    def items(count):
        return [
            ft.Container(
                content=ft.Text(value=str(i)),
                alignment=ft.alignment.center,
                width=50,
                height=50,
                bgcolor=ft.Colors.AMBER,
                border_radius=ft.border_radius.all(5),
            ) for i in range(1, count + 1)
        ]

    def spacing_slider_change(e):
        col.spacing = int(e.control.value)
        col.update()

    gap_slider = ft.Slider(
        min=0, max=100, divisions=10, value=0, label="{value}", width=500,
        on_change=spacing_slider_change,
    )

    col = ft.Column(spacing=0, controls=items(5))
    page.add(ft.Column([ft.Text("Spacing between items"), gap_slider]), col)

ft.app(main)

Column Wrapping

By enabling the wrap property, child controls will be placed into additional columns if they exceed the available height.

import flet as ft

HEIGHT = 400

def main(page: ft.Page):
    def items(count):
        return [
            ft.Container(
                content=ft.Text(value=str(i)),
                alignment=ft.alignment.center,
                width=30,
                height=30,
                bgcolor=ft.Colors.AMBER,
                border_radius=ft.border_radius.all(5),
            ) for i in range(1, count + 1)
        ]

    def slider_change(e):
        col.height = float(e.control.value)
        col.update()

    width_slider = ft.Slider(
        min=0, max=HEIGHT, divisions=20, value=HEIGHT, label="{value}", width=500,
        on_change=slider_change,
    )

    col = ft.Column(
        wrap=True, spacing=10, run_spacing=10, controls=items(10), height=HEIGHT,
    )

    page.add(ft.Column([ft.Text("Adjust column height to see wrapping effect:"), width_slider]), ft.Container(content=col, bgcolor=ft.Colors.AMBER_100))

ft.app(main)

Vertical Alignment

You can align child elements within a Column using MainAxisAlignment.

import flet as ft

def main(page: ft.Page):
    def items(count):
        return [
            ft.Container(
                content=ft.Text(value=str(i)),
                alignment=ft.alignment.center,
                width=50,
                height=50,
                bgcolor=ft.Colors.AMBER_500,
            ) for i in range(1, count + 1)
        ]

    def column_with_alignment(align: ft.MainAxisAlignment):
        return ft.Column([
            ft.Text(str(align), size=10),
            ft.Container(
                content=ft.Column(items(3), alignment=align),
                bgcolor=ft.Colors.AMBER_100,
                height=400,
            ),
        ])

    page.add(ft.Row([
        column_with_alignment(ft.MainAxisAlignment.START),
        column_with_alignment(ft.MainAxisAlignment.CENTER),
        column_with_alignment(ft.MainAxisAlignment.END),
        column_with_alignment(ft.MainAxisAlignment.SPACE_BETWEEN),
        column_with_alignment(ft.MainAxisAlignment.SPACE_AROUND),
        column_with_alignment(ft.MainAxisAlignment.SPACE_EVENLY),
    ], spacing=30, alignment=ft.MainAxisAlignment.START))

ft.app(main)

Horizontal Alignment

To align elements horizontally within a Column, use CrossAxisAlignment.

import flet as ft

def main(page: ft.Page):
    def items(count):
        return [
            ft.Container(
                content=ft.Text(value=str(i)),
                alignment=ft.alignment.center,
                width=50,
                height=50,
                bgcolor=ft.Colors.AMBER_500,
            ) for i in range(1, count + 1)
        ]

    def column_with_horiz_alignment(align: ft.CrossAxisAlignment):
        return ft.Column([
            ft.Text(str(align), size=16),
            ft.Container(
                content=ft.Column(items(3), alignment=ft.MainAxisAlignment.START, horizontal_alignment=align),
                bgcolor=ft.Colors.AMBER_100,
                width=100,
            ),
        ])

    page.add(ft.Row([
        column_with_horiz_alignment(ft.CrossAxisAlignment.START),
        column_with_horiz_alignment(ft.CrossAxisAlignment.CENTER),
        column_with_horiz_alignment(ft.CrossAxisAlignment.END),
    ], spacing=30, alignment=ft.MainAxisAlignment.START))

ft.app(main)

Infinite Scroll List

The Column widget supports infinite scrolling by dynamically adding items as the user scrolls.

import threading
import flet as ft

class State:
    i = 0

s = State()
sem = threading.Semaphore()

def main(page: ft.Page):
    def on_scroll(e: ft.OnScrollEvent):
        if e.pixels >= e.max_scroll_extent - 100:
            if sem.acquire(blocking=False):
                try:
                    for _ in range(10):
                        cl.controls.append(ft.Text(f"Text line {s.i}", key=str(s.i)))
                        s.i += 1
                    cl.update()
                finally:
                    sem.release()

    cl = ft.Column(spacing=10, height=200, width=200, scroll=ft.ScrollMode.ALWAYS, on_scroll=on_scroll)
    for _ in range(50):
        cl.controls.append(ft.Text(f"Text line {s.i}", key=str(s.i)))
        s.i += 1

    page.add(ft.Container(cl, border=ft.border.all(1)))

ft.app(main)

Conclusion

The Column control in Flet is an essential component for organizing UI elements vertically. With properties like spacing, wrapping, alignment, and scrolling, it provides extensive flexibility for designing interactive applications. By leveraging these features, developers can create highly responsive and visually appealing interfaces.