Column#

A container that lays out its children in a single vertical column, top to bottom. By default each child keeps its natural height and the group sits at the top edge.

Column — light theme Column — dark theme

Usage#

A column lays its children out top to bottom. By default they keep their natural height — use gap= to space them, horizontal_items= to align them on the cross axis, and a child’s grow=True (or a Spacer) to fill the leftover height.

Gap#

gap= sets uniform spacing in pixels between children.

# gap=8 — rows close together
with bs.Column(gap=8, show_border=True, padding=8, horizontal_items="stretch"):
    for lbl in ("A", "B", "C"):
        bs.Button(lbl)

# gap=24 — rows spread apart
with bs.Column(gap=24, show_border=True, padding=8, horizontal_items="stretch"):
    for lbl in ("A", "B", "C"):
        bs.Button(lbl)
Column gap — light theme Column gap — dark theme

Cross-axis alignment#

horizontal_items= aligns children left and right within the column. 'left', 'center' (the default), and 'right' size each child to its content and pin it to that edge; 'stretch' makes every child fill the column width — the usual choice for a form column. Override a single child with horizontal=.

with bs.Column(horizontal_items="center", show_border=True, padding=8):
    bs.Button("Save")

with bs.Column(horizontal_items="stretch", show_border=True, padding=8):
    bs.Button("Save")          # fills the column width
Column alignment — light theme Column alignment — dark theme

Arranging the group#

vertical_items= positions the whole group of children down the column. 'top' (the default), 'center', and 'bottom' cluster them at one edge; 'space-between', 'space-around', and 'space-evenly' distribute them across the full height. (It has no effect once a child grows.)

Arrangement only has room to act when the column is taller than its children, so these examples set a fixed height=.

# cluster the group at one edge
with bs.Column(vertical_items="center", height=140,
               show_border=True, padding=8, horizontal_items="stretch"):
    bs.Button("Header")
    bs.Button("Footer")

# distribute the group across the full height
with bs.Column(vertical_items="space-evenly", height=140,
               show_border=True, padding=8, horizontal_items="stretch"):
    bs.Button("Header")
    bs.Button("Footer")
Column arrangement — light theme Column arrangement — dark theme

Growing a child#

grow=True lets one child claim and fill the leftover height while the others keep their natural size — ideal for a content area between a fixed header and footer.

with bs.Column(gap=6, height=150, horizontal_items="stretch"):
    bs.Button("Header")
    bs.Button("Content", grow=True)   # fills the middle
    bs.Button("Footer")
Column grow — light theme Column grow — dark theme

Proportional heights#

weights= sizes children by a fixed ratio rather than by content. weights=[1, 2, 1] makes the middle child twice as tall as each neighbor, the three together filling the column.

with bs.Column(gap=8, weights=[1, 2, 1], height=220, horizontal_items="stretch"):
    bs.Button("One"); bs.Button("Two"); bs.Button("Three")
Column proportional heights — light theme Column proportional heights — dark theme

Spacer#

A Spacer is a local break that pushes its neighbors apart — drop one in to send a footer to the bottom without fixing the column height. Where vertical_items moves the whole group, a Spacer opens a gap at one point.

with bs.Column(gap=6, height=150, horizontal_items="stretch"):
    bs.Button("Header")
    bs.Spacer()                       # pushes the footer to the bottom
    bs.Button("Footer")
Column spacer — light theme Column spacer — dark theme

Background#

surface= sets the container background. It accepts a surface token ('content', 'card', 'chrome', 'overlay') or any accent token ('primary', 'success', etc.) with optional modifiers:

with bs.Column(surface="card", padding=12, gap=8):
    bs.Label("Sits on card surface")

with bs.Column(surface="primary[subtle]", padding=12, gap=8):
    bs.Label("Accent-tinted background")

Border#

show_border=True draws a 1 px border along the inside edge of the frame. Without padding, children render flush against it. Use at least padding=1 to give the border visual clearance.

with bs.Column(gap=8, show_border=True, padding=8, horizontal_items="stretch"):
    bs.Button("A")
    bs.Button("B")
    bs.Button("C")

Self-placement#

horizontal, vertical, and grow control how the Column places itself within its parent — separate from how it arranges its own children. In a horizontal parent, grow=True lets a Column claim the leftover width — a fixed sidebar beside a growing content area.

with bs.Row(gap=12, horizontal="stretch"):
    with bs.Column(gap=8, width=180):              # fixed-width sidebar
        bs.Button("Inbox"); bs.Button("Drafts")
    with bs.Column(grow=True, horizontal_items="stretch"):
        bs.Label("Content", font="heading-md")     # claims the rest
Column self-placement — light theme Column self-placement — dark theme

Widget sizing#

All widgets accept self-placement kwargs via **kwargs. The parent container determines which options apply — Column / Row parents use the layout kwargs below, grid-based parents use grid kwargs.

Column (vertical layout)

Used inside a Column, App, or any other container with a column layout. Children are arranged top-to-bottom, so horizontal aligns each child across the width and grow shares the vertical space. (vertical does not apply — the order of the children sets their top-to-bottom position.)

horizontal

Cross-axis placement of the widget: 'left', 'center', 'right', or 'stretch' to fill the available width.

grow

Claim and fill a share of the leftover vertical space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Row (horizontal layout)

Used inside a Row or any other container with a row layout. Children are arranged left-to-right, so vertical aligns each child across the height and grow shares the horizontal space. (horizontal does not apply — the order of the children sets their left-to-right position.)

vertical

Cross-axis placement of the widget: 'top', 'center', 'bottom', or 'stretch' to fill the available height.

grow

Claim and fill a share of the leftover horizontal space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Grid

Used inside a Grid container.

row / column

Zero-based row and column indices.

rowspan / columnspan

Number of rows or columns to span.

horizontal

Horizontal placement within the grid cell: 'left', 'center', 'right', or 'stretch' to fill the cell width.

vertical

Vertical placement within the grid cell: 'top', 'center', 'bottom', or 'stretch' to fill the cell height.

margin

External spacing in pixels. Accepts an integer, a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing. Accepts an integer or (left, right).

margin_y

Vertical external spacing. Accepts an integer or (top, bottom).

See also#

Row — horizontal equivalent. Spacer — a composable break that pushes neighbors apart. Grid — row and column layout. Card and GroupBox — a Row/Column with an elevated background or labelled border.

API#

The complete reference for Column lives on the Widgets API page. At a glance:

Column

Lays out children top to bottom along the vertical axis.

Full Example#

 1
 2with bs.App(title="Column Demo", minsize=(720, 500), padding=20, gap=16) as app:
 3
 4    with bs.Row(gap=16, horizontal="stretch", vertical_items="top"):
 5
 6        # gap
 7        with bs.Column(gap=4, grow=True):
 8            bs.Label("gap", font="heading-sm")
 9            with bs.Column(show_border=True, gap=8, padding=8,
10                           horizontal="stretch", horizontal_items="stretch"):
11                [bs.Button(lbl) for lbl in ("A", "B", "C")]
12
13        # horizontal_items — cross-axis alignment of the children
14        with bs.Column(gap=4, grow=True):
15            bs.Label("horizontal_items", font="heading-sm")
16            for alignment in ("left", "center", "right", "stretch"):
17                bs.Label(f"={alignment!r}", font="caption")
18                with bs.Column(horizontal_items=alignment, show_border=True,
19                               padding=8, horizontal="stretch"):
20                    bs.Button("Save")
21
22    # vertical_items — arrange the whole group down the column
23    bs.Label("vertical_items", font="heading-sm")
24    with bs.Row(gap=16, horizontal="stretch", vertical_items="top"):
25        for arrangement in ("top", "center", "bottom", "space-between"):
26            with bs.Column(gap=4, grow=True):
27                bs.Label(f"={arrangement!r}", font="caption")
28                with bs.Column(vertical_items=arrangement, show_border=True,
29                               padding=8, height=140, horizontal="stretch",
30                               horizontal_items="stretch"):
31                    bs.Button("Header")
32                    bs.Button("Footer")
33
34    # grow — one child claims and fills the leftover height
35    bs.Label("grow", font="heading-sm")
36    with bs.Column(gap=6, show_border=True, padding=8, height=150,
37                   horizontal="stretch", horizontal_items="stretch"):
38        bs.Button("Header")
39        bs.Button("Content", grow=True)   # fills the middle
40        bs.Button("Footer")
41
42    # Spacer — push a footer to the bottom without a fixed height
43    bs.Label("Spacer", font="heading-sm")
44    with bs.Column(gap=6, show_border=True, padding=8, height=150,
45                   horizontal="stretch", horizontal_items="stretch"):
46        bs.Button("Header")
47        bs.Spacer()
48        bs.Button("Footer")
49
50app.run()