GridFrame
GridFrame is a layout container with simplified grid-based layout management and auto-placement.
It extends the bootstack Frame with automatic grid-based layout management, including support for row/column definitions, gap spacing, auto-placement, and default sticky behavior. Use GridFrame when you need a CSS Grid-like layout experience without manually managing grid options.
Children simply call the standard grid() method and automatically receive the frame's default layout options and auto-placement.
Quick start
import bootstack as bs
app = bs.App()
# 2x2 grid with gap
grid = bs.GridFrame(app, columns=2, rows=2, gap=10, padding=20)
grid.pack(fill="both", expand=True)
# Widgets are auto-placed in row-major order using standard grid()
bs.Button(grid, text="Top-Left").grid()
bs.Button(grid, text="Top-Right").grid()
bs.Button(grid, text="Bottom-Left").grid()
bs.Button(grid, text="Bottom-Right").grid()
app.mainloop()
When to use
Use GridFrame when:
- you need a 2D grid layout
- you want CSS Grid-like auto-placement
- you need consistent gap spacing between cells
- you want to define row/column sizes declaratively
Consider a different control when:
- you only need a 1D stack -> use PackFrame
- you just need a container without layout management -> use Frame
- you need resizable split regions -> use PanedWindow
Appearance
Styling
GridFrame inherits all styling options from Frame. Use accent for semantic tokens.
bs.GridFrame(app, accent="secondary", padding=20)
Design System
For theming details and color tokens, see Design System.
Examples & patterns
rows / columns
Define the grid structure. Can be an integer (number of equal-weight rows/columns) or a list of size specs.
# Simple 3x3 grid
bs.GridFrame(app, rows=3, columns=3)
# Custom column weights
bs.GridFrame(app, columns=[1, 2, 1]) # Middle column gets 2x weight
# Fixed-size and auto columns
bs.GridFrame(app, columns=["200px", 1, "auto"])
Size specs:
- Integer: weight for flexible sizing (like CSS fr units)
"auto": size to content"100px": fixed pixel size
gap
Spacing between cells. Can be uniform or separate column/row gaps.
# Uniform 10px gap
bs.GridFrame(app, gap=10)
# Different column and row gaps
bs.GridFrame(app, gap=(8, 12)) # (column_gap, row_gap)
sticky_items
Default sticky value for all children.
# All widgets stretch to fill their cell
bs.GridFrame(app, columns=2, sticky_items="nsew")
auto_flow
Control how widgets are auto-placed. Options: "row", "column", "row-dense", "column-dense", "none".
# Fill by rows (default)
bs.GridFrame(app, columns=3, auto_flow="row")
# Fill by columns
bs.GridFrame(app, columns=3, auto_flow="column")
# Dense packing (fills gaps)
bs.GridFrame(app, columns=3, auto_flow="row-dense")
propagate
Control whether the frame resizes to fit its contents.
grid = bs.GridFrame(app, width=400, height=300, propagate=False)
Adding widgets
Children use standard grid() to add themselves. The frame automatically applies its defaults and handles auto-placement.
grid = bs.GridFrame(app, columns=3, gap=8, sticky_items="nsew")
# Auto-placed widgets (row-major order by default)
bs.Button(grid, text="A").grid() # row=0, col=0
bs.Button(grid, text="B").grid() # row=0, col=1
bs.Button(grid, text="C").grid() # row=0, col=2
bs.Button(grid, text="D").grid() # row=1, col=0
# Explicit position
bs.Button(grid, text="Footer").grid(row=2, column=0, columnspan=3)
# With spanning
bs.Label(grid, text="Wide").grid(columnspan=2)
# Override default sticky
bs.Label(grid, text="Centered").grid(sticky="")
Method chaining
The grid() method returns the widget for chaining:
btn = bs.Button(grid, text="Click").grid()
btn.configure(command=my_callback)
# Or chain further
bs.Entry(grid).grid(columnspan=2).focus()
Removing widgets
Use standard grid_forget() to remove widgets:
btn = bs.Button(grid, text="Removable").grid()
# Later, remove it
btn.grid_forget()
Configuring rows and columns
# Configure a specific row
grid.configure_row(0, weight=1, minsize=50)
# Configure a specific column
grid.configure_column(1, weight=2, minsize=100)
Behavior
-
Widgets are auto-placed in row-major order by default (configurable via
auto_flow). -
The
grid()method returns the widget for fluent/chaining patterns. -
Removing widgets automatically adjusts auto-placement for remaining widgets.
-
Per-widget options in
grid()override container defaults. -
Gap spacing is applied as padding on non-first rows/columns.
-
GridFrame extends Frame, so all Frame options (color, padding, etc.) are available.
-
Standard tkinter grid options (
row,column,rowspan,columnspan,sticky, etc.) work as expected.
Additional resources
Related widgets
- PackFrame -- pack-based layout container
- Frame -- basic container
- LabelFrame -- container with visible label
- PanedWindow -- resizable split regions