Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

row and column

Boxes that flow their children along one axis: a row left to right, a column top to bottom. They are the main layout tools; everything else is placed inside one. The two accept the same properties and differ only in their main axis. For children built from data, use a list.

A meter: a "Fill"-wide track with a percentage-wide fill that follows a signal.

local volume = state("volume", 0.45)

local meter = row {
    width = "Fill",
    height = 6,
    radius = 3,
    background = "#313244",
    children = { rect {
        width = volume:map(function(v) return string.format("%d%%", math.floor((v or 0) * 100 + 0.5)) end),
        height = "Fill",
        radius = 3,
        background = "#89B4FA",
        animate = { width = 150 },
    } },
}

return column { width = 240, children = { meter } }

Properties

row and column take the common and box properties, plus:

PropertyTypeDefaultBehaviour
childrenNode[]|BoundNoneArray of node tables, up to 10000; a nil or false entry is an error. Laid out in order along the main axis. Bind a signal of an array to switch views
spacingnumber|Bound0Px between visible children; negative values overlap them. Not range-checked
scrollBoundNoneA scroll(name) signal; makes the node a scrolling viewport along its main axis (scroll)

How the container packs its children:

AxisSet byEffect
Main (row: horizontal, column: vertical)The container’s own align_h (row) or align_v (column)"Start", "Center", "End" pack the children; "Stretch" packs like "Start". The children’s own value on this axis is ignored
CrossEach child’s align_v (row) or align_h (column)Places that child across the row’s height or the column’s width; "Stretch" fills it

"Fill" children along the main axis share what the others leave, and no child shrinks; see sizes.

How do I…

TaskAnswer
Show a progress barThe meter above
Push items apartBelow
Split a bar into three groupsThe bar: two "Fill" rows around a content-sized middle
Centre items in a rowalign_h = "Center" on the row itself
Make children equal widthGive each width = "Fill"
Scroll overflowing contentBound the axis (height or max_height on a column), then scroll = scroll("name") (scroll)
Overlap items, like stacked avatarsNegative spacing

Push items apart

A "Fill" child takes the space its siblings leave, so a bare rect makes a spacer:

local header = row {
    width = 300,
    spacing = 8,
    children = {
        text { content = "Wi-Fi", font_size = 14, foreground = "#CDD6F4", align_v = "Center" },
        rect { width = "Fill" }, -- takes the space left over, pushing what follows to the end
        text { content = "Connected", foreground = "#A6ADC8", align_v = "Center" },
    },
}

return header

Gotchas

TrapFix
align_h = "Center" on a child of a row does nothingThe row packs its main axis: set align_h on the row, or use "Fill" spacers
align_v = "Center" on a row leaves its children at the topA row’s own align_v places the row in its parent. Set align_v on each child, as in push items apart
A "Fill" child of a content-sized row is 0 wideThe row has no leftover space to share. Give the row a width or "Fill"
direction = "Horizontal" on a column is refuseddirection is a list property. Use a row
A scroll row or column never scrollsIts size on the main axis is content-sized, so nothing overflows. Set width/height or a max_*

See also: list, rect, layout model.

Source: vocabulary, layout solver, spacing and alignment parsers, scroll.