Skip to content
View as Markdown

Layout

LoamUI ships no layout components. Layout is a native CSS concern, and the platform already has four layout modules that cover the cases a UI runs into. Pick the one that fits the shape of the content, write it in the component that owns that content, and reach for the space tokens for every gap. This page is itself laid out this way.

Pick the module by the shape of the content

Each module answers a different question. Match it to what you are arranging, not to a breakpoint.

The contentThe moduleThe core declaration
A page of proseFlownothing; block layout is the default
A dense dashboardGriddisplay: grid with subgrid for alignment
A row of controlsFlexdisplay: flex
A long articleMulti-columncolumns

Flow, for a documentation page

Normal flow stacks blocks in source order, and the element styles already give every block its own block-end margin, so a column of prose needs no layout code at all. Where you want to tune the rhythm, set the gap with a space token on the container rather than adding margins.

A heading

A paragraph sits below it, spaced by the element styles.

The next paragraph follows in source order. No layout code runs here.

Grid, for an information-dense dashboard

Grid is the two-dimensional module: use it when rows and columns both matter. Prefer intrinsic, fluid track sizing over media queries. repeat(auto-fit, minmax(min(16rem, 100%), 1fr)) lays out as many equal columns as fit and reflows itself as the container resizes, with no breakpoints to maintain. When sibling cards must align their internal rows, give them grid-template-rows: subgrid.

@scope (.dashboard) {  :scope {    display: grid;    gap: var(--loam-space-lg);    grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));  }}
Panel
Panel
Panel
Panel

Flex, for a one-dimensional control row

Flex is the one-dimensional module: a row (or column) of items that share a line and wrap when they run out of room. It is the right tool for a button group, a toolbar, or a label beside its control. Let it wrap, align it safe so a focused item is never clipped, and space it with a token.

@scope (.actions) {  :scope {    display: flex;    flex-wrap: wrap;    gap: var(--loam-space-sm);    align-items: safe center;  }}
Save
Save and continue
Cancel

Multi-column, for a long article

Multi-column flows a single stream of text across balanced columns, the way a newspaper does. Set a column width and let the browser decide the count from the available space.

@scope (.article) {  :scope {    columns: 18rem;    gap: var(--loam-space-xl);  }}

Space with tokens, not numbers

Whichever module you pick, the gaps come from the fluid space scale, not hard-coded lengths. A token gap grows a little on a wide container and tightens on a narrow one, so a layout keeps its rhythm across sizes without a single media query.

/* the scale, smallest to largest */gap: var(--loam-space-xs); /* 4px  → 4.5px  */gap: var(--loam-space-sm); /* 8px  → 9px    */gap: var(--loam-space-md); /* 12px → 13.5px */gap: var(--loam-space-lg); /* 16px → 18px   */gap: var(--loam-space-xl); /* 24px → 27px   */

The same discipline the components use is available to your own layouts: a native module for structure, a space token for every gap, and a container query where a piece needs to respond to its own width rather than the viewport's.