Alignment and Distribution
A container places its children along two axes.
The justify_children_* utilities distribute them along the main axis
(across a row, down a col),
and the align_children_* utilities place them on the cross axis.
A child can override its parent's cross-axis alignment for itself with align_self_*.
The examples on this page title each panel with this helper, which draws its text over the top border:
def title(content: str) -> Text:
return Text(content=f" {content} ", style=position_absolute | inset_top(-1) | inset_left(1))
Distributing children along the main axis
The justify_children_* utilities share out the free space a row or column has left over
after its children take their sizes.
Children that grow leave no free space, so these only matter when nothing claims it.
@component
def justify() -> Div:
return Div(
style=col,
children=[
Div(
style=row | justify | border,
children=[
title(name),
Text(style=border | border_heavy, content="a"),
Text(style=border | border_heavy, content="bb"),
Text(style=border | border_heavy, content="ccc"),
],
)
for name, justify in (
("justify_children_start", justify_children_start),
("justify_children_center", justify_children_center),
("justify_children_end", justify_children_end),
("justify_children_space_between", justify_children_space_between),
("justify_children_space_around", justify_children_space_around),
("justify_children_space_evenly", justify_children_space_evenly),
)
],
)
┌─ justify_children_start ───────────────────────┐
│┏━┓┏━━┓┏━━━┓ │
│┃a┃┃bb┃┃ccc┃ │
│┗━┛┗━━┛┗━━━┛ │
└────────────────────────────────────────────────┘
┌─ justify_children_center ──────────────────────┐
│ ┏━┓┏━━┓┏━━━┓ │
│ ┃a┃┃bb┃┃ccc┃ │
│ ┗━┛┗━━┛┗━━━┛ │
└────────────────────────────────────────────────┘
┌─ justify_children_end ─────────────────────────┐
│ ┏━┓┏━━┓┏━━━┓│
│ ┃a┃┃bb┃┃ccc┃│
│ ┗━┛┗━━┛┗━━━┛│
└────────────────────────────────────────────────┘
┌─ justify_children_space_between ───────────────┐
│┏━┓ ┏━━┓ ┏━━━┓│
│┃a┃ ┃bb┃ ┃ccc┃│
│┗━┛ ┗━━┛ ┗━━━┛│
└────────────────────────────────────────────────┘
┌─ justify_children_space_around ────────────────┐
│ ┏━┓ ┏━━┓ ┏━━━┓ │
│ ┃a┃ ┃bb┃ ┃ccc┃ │
│ ┗━┛ ┗━━┛ ┗━━━┛ │
└────────────────────────────────────────────────┘
┌─ justify_children_space_evenly ────────────────┐
│ ┏━┓ ┏━━┓ ┏━━━┓ │
│ ┃a┃ ┃bb┃ ┃ccc┃ │
│ ┗━┛ ┗━━┛ ┗━━━┛ │
└────────────────────────────────────────────────┘
Aligning children on the cross axis
The default, align_children_stretch, fills the cross axis;
the others keep each child at its content size and place it.
@component
def align() -> Div:
return Div(
style=row,
children=[
Div(
style=row | align | fill(1) | border,
children=[
title(name),
Text(style=border | border_heavy, content="a"),
Text(style=border | border_heavy, content="b\nb"),
Text(style=border | border_heavy, content="c\nc\nc"),
],
)
for name, align in (
("align_children_start", align_children_start),
("align_children_center", align_children_center),
("align_children_end", align_children_end),
("align_children_stretch", align_children_stretch),
)
],
)
┌─ align_children_start ─────┐┌─ align_children_center ────┐┌─ align_children_end ───────┐┌─ align_children_stretch ───┐
│┏━┓┏━┓┏━┓ ││ ││ ││┏━┓┏━┓┏━┓ │
│┃a┃┃b┃┃c┃ ││ ┏━┓ ││ ││┃a┃┃b┃┃c┃ │
│┗━┛┃b┃┃c┃ ││┏━┓┏━┓┃c┃ ││ ┏━┓ ││┃ ┃┃b┃┃c┃ │
│ ┗━┛┃c┃ ││┃a┃┃b┃┃c┃ ││ ┏━┓┃c┃ ││┃ ┃┃ ┃┃c┃ │
│ ┗━┛ ││┗━┛┃b┃┃c┃ ││┏━┓┃b┃┃c┃ ││┃ ┃┃ ┃┃ ┃ │
│ ││ ┗━┛┗━┛ ││┃a┃┃b┃┃c┃ ││┃ ┃┃ ┃┃ ┃ │
│ ││ ││┗━┛┗━┛┗━┛ ││┗━┛┗━┛┗━┛ │
└────────────────────────────┘└────────────────────────────┘└────────────────────────────┘└────────────────────────────┘
Aligning one child
align_self_* on a child replaces its parent's align_children_* for that child alone.
@component
def align_self() -> Div:
return Div(
style=row | align_children_start | gap(1) | border,
children=[
title("row | align_children_start"),
Text(style=border | border_heavy, content="no align_self"),
Text(style=align_self_center | border | border_heavy, content="align_self_center"),
Text(style=align_self_end | border | border_heavy, content="align_self_end"),
Text(style=align_self_stretch | border | border_heavy, content="align_self_stretch"),
],
)
┌─ row | align_children_start ─────────────────────────────────────────────────┐
│┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━┓ │
│┃no align_self┃ ┃align_self_stretch┃ │
│┗━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━━━━┓ ┃ ┃ │
│ ┃align_self_center┃ ┃ ┃ │
│ ┗━━━━━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━┓ ┃ ┃ │
│ ┃align_self_end┃ ┃ ┃ │
│ ┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━┛ │
└──────────────────────────────────────────────────────────────────────────────┘
Centering a box
Center a box on both axes with center_children,
which is justify_children_center | align_children_center.
It works in a grid too: there it centers the grid's tracks,
and a grid with no template sizes its one track to fit its lone child.
To center a box over other content rather than among it, see
A dialog centered over the app.
@component
def center() -> Div:
return Div(
style=row,
children=[
Div(
style=row | center_children | fill(1) | border,
children=[title("flexbox"), Text(style=border | border_heavy, content="centered")],
),
Div(
style=display_grid | center_children | fill(1) | border,
children=[title("grid"), Text(style=border | border_heavy, content="centered")],
),
],
)
Content larger than its container
The *_center and *_end utilities are CSS's safe alignments:
content too large for its container starts at the container's start edge
and overflows only past the end, so its beginning stays on screen.
Each has an *_unsafe counterpart with CSS's default behavior,
which centers or end-aligns the content anyway and overflows past the start edge too.
@component
def overflow() -> Div:
return Div(
style=row | pad_y(4),
children=[
Div(
style=col | justify | fill(1) | border,
children=[title(name), Text(content=TALL)],
)
for name, justify in (
("justify_children_center", justify_children_center),
("justify_children_center_unsafe", justify_children_center_unsafe),
)
],
)