jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

registry:ui · Layout · alpha

prototype-waterfall — the standardized masonry

The layout family, alpha track, on the CSS multicol engine: the columns shorthand passes through verbatim — a number is the count form, a length string is the auto-width floor — with column-fill: balance (browser-equalized heights) and column-gap. The tradeoffs are declared, not hidden: children flow in column (newspaper) order, and break-inside stays the consumer's call.

install — prototype-waterfall

$npx jixoai-ui add prototype-waterfall

https://ui.jixoai.com/r/prototype-waterfall.json

alpha track CSS multicol engine columns: count or auto-width floor balanced fill inline style only

overview

Overview

The trio's third member: masonry on the multicol engine — two columns forms, one strategy seam, and the tradeoffs said out loud.

The three alpha laws carry over unchanged: SINGLE ROOT + REST SPREAD (one div; consumer attributes first, family stamps after), ZERO TRANSLATION (the columns shorthand IS the CSS — a number is the count form, a length string ('14rem') is the auto-width FLOOR where the count follows the viewport; one property covers both shapes with no branching), and INLINE STYLE ONLY (no utilities, no theme tokens, no css file). There is NO JavaScript in the family — no resize observation, no absolute positioning, no layout-settling timer: the browser's column balancer is the engine, so reflow on any control change is immediate and native (measured in the task-37 probe: each rig change settles by the first animation frame — the same-task read is stale at Svelte's flush boundary).

The declared tradeoffs (honest, not hidden): children flow in COLUMN order — down column one, then column two, newspaper order, not shortest-column-first masonry — and break-inside stays the consumer's call (the component never overrides it; pass style="break-inside: avoid" on cards you refuse to split). The strategy prop ships with a single member — 'balanced' → column-fill: balance, the browser equalizing column heights — as the seam for a future 'ordered' (JS-measured shortest-column placement) to join the union non-breakingly.

The eight axes are forwarders as on the trio's first two members: all no-own, carriers in the consumer style attr, density stamping its rung for descendants, theme riding the .dark bridge. A waterfall-specific nuance measured below: BOTH column forms are §11-stamp-scale-blind — the rem floor reads the DOCUMENT root, not the element stamp (stamp 18px → the 224px floor unchanged; document root 16→20px → 280px; two-direction probe). Reading order is coherent — the browser fills column one first, so announced order matches the visual column sequence — but content is segmented: a card straddling a column break is split unless you forbid it.

prototype-waterfall · the rig

The property panel, live: the columns shorthand in both forms plus gap — measured end-to-end in task 37 against the container's resolved column geometry (computed column-count / column-width, and the laid-out count from where the cards land).

w1 · 64pxw2 · 116pxw3 · 88pxw4 · 140pxw5 · 72pxw6 · 104pxw7 · 96pxw8 · 128pxw9 · 60px
  • columns form
  • gap (px)
  • the count form fixes the columns; the "14rem" form fixes the WIDTH and lets the count follow the viewport (the masonry floor — measured 3 columns at 1400px, fewer as it narrows). Cards carry break-inside: avoid — a card never splits across a column break.

prototype-waterfall-usage.svelte svelte
<PrototypeWaterfall
  columns={3}
  gap={16}
  strategy="balanced"
>
  <!-- nine variable-height cards; break-inside is yours -->
</PrototypeWaterfall>

law

The alpha contract + the multicol tradeoffs

The three trio laws hold verbatim; the waterfall adds the columns-shorthand duality and says its tradeoffs out loud — column order and the consumer's break-inside.

1 · SINGLE ROOT + REST SPREAD — one div, consumer attributes first, family stamps after. 2 · ZERO TRANSLATION — columns is the CSS columns shorthand (count form and auto-width form in one property, no branching); gap is column-gap; strategy is column-fill. 3 · INLINE STYLE ONLY — zero tokens, any host. The declared tradeoffs: children flow in column order (newspaper order — announced order matches the visual column sequence), and break-inside is never overridden by the component. The 'ordered' strategy (JS-measured shortest-column placement) is the recorded future seam — the prop ships now so the union can grow without breaking v0 consumers.

The layout trio, cross-referenced: prototype-flex — the row prototype-grid — the tracks prototype-waterfall — the columns — one contract, three engines.

types

Types — the columns forms, rendered

The shorthand's two shapes on identical card decks: the count form fixes the columns; the auto-width form fixes the width and lets the count follow — the masonry floor.

prototype-waterfall · columns forms

count form: columns={4}
w1w2w3w4w5w6w7w8w9
auto-width floor: columns="10rem"
w1w2w3w4w5w6w7w8w9
prototype-waterfall-usage.svelte svelte
<PrototypeWaterfall columns={3} gap={16}>
  {#each cards as card (card.id)}
    <figure style="break-inside: avoid;">…</figure>
  {/each}
</PrototypeWaterfall>

<!-- the auto-width form: a column LENGTH floors the width, count follows -->
<PrototypeWaterfall columns="14rem" gap={16}>…</PrototypeWaterfall>

usage

Usage

Pass a count or a length; add break-inside: avoid to the cards you refuse to split.

PrototypeWaterfall usage
<PrototypeWaterfall columns={3} gap={16}>
  {#each cards as card (card.id)}
    <figure style="break-inside: avoid;">…</figure>
  {/each}
</PrototypeWaterfall>

<!-- the auto-width form: a column LENGTH floors the width, count follows -->
<PrototypeWaterfall columns="14rem" gap={16}>…</PrototypeWaterfall>

api

API

One shorthand, one gap, one strategy seam — everything else rides through as native div attributes.

Properties

PropertyTypeDefaultDescription
columns number | string—The CSS columns shorthand, verbatim: number = the count form; a length string ("14rem") = the auto-width floor — the count follows the viewport.
gap number | string—column-gap: number → px, string verbatim.
strategy 'balanced'—v0's single member → column-fill: balance (browser-equalized heights). 'ordered' (JS-measured shortest-column placement) is the recorded future seam — the prop ships now for it.
class string—Passed through verbatim — the component owns no class of its own.
...rest HTMLAttributes<HTMLDivElement>spreadEvery other attribute lands on the single root (stamped data-jx-prototype-waterfall after the spread — replace, never merge).

Universal props

PropertyTypeDefaultDescription
size'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopethe base scale — root font-size; parts size in em
shape'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto' · ambient scopecorner geometry (CSS corner-shape; §14 degrade table)
radius'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopecorner size; auto = the concentric broadcast (§3)
density'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopespacing/leading scale over the kernel channels (§4)
color'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto' · ambient scopethe hue axis of the fixed oklch primary system (§5)
theme'light' | 'dark' | 'system' | 'auto''auto' · ambient scopelight/dark profile; system = the JS-mutable global (§6)
elevation'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto' · ambient scopeofficial M3 levels over the surface ladder (§7)
motion'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto' · ambient scopeintensity across the motion kernels (§8)

axes

The eight axes on prototype-waterfall

The zero-translation posture extends to paint: the first-time contract is ALL NO-OWN, and the family paints nothing for any axis — carriers join the consumer style attr, density stamps its rung for descendants, theme rides the .dark bridge. One measured nuance: both column forms are stamp-scale-blind — the rem floor reads the document root (stamp 18px keeps the 224px floor; root 16→20px moves it to 280px).

PropertyTypeDefaultDescription
density '2xs' | 'xs' | 'sm' | 'default' | 'lg' | 'auto' | number (+ the five legacy spellings)'auto'FORWARDER — the resolved rung stamps data-density on the waterfall root (measured data-density=lg explicit; null ambient), opening the kernel channels for DESCENDANTS; the column geometry consumes none. Number unit: coefficient.
size 'small' | 'medium' | 'large' | 'auto' | number'auto'FORWARDER, ECHO MEASURED — the §11 stamp lands inline as font-size: var(--jx-size-effective, 1rem) (measured in the style attr; computed 18px at size={18}); the stamp is ELEMENT-LEVEL — column floors do NOT follow it ('14rem' reads the document root: stamp 18px keeps the 224px floor; document root 16→20px moves it to 280px — both forms stamp-scale-blind, two-direction probe). Number unit: px.
shape 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto'FORWARDER — carrier stamp only; zero family readers. Number unit: none.
radius 'small' | 'medium' | 'large' | 'auto' | number'auto'FORWARDER — carrier stamp only; zero family readers. Number unit: px.
color 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto'FORWARDER — carrier stamp only; zero family readers. Number unit: hue degrees.
theme 'light' | 'dark' | 'system' | 'auto''auto'FORWARDER — dark rides the .dark class bridge on the waterfall root (measured with theme="dark"), re-scoping token chains for the subtree; the column geometry is theme-blind. No number lane.
elevation 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto'FORWARDER — carrier stamp only; zero family readers. Number unit: dp.
motion 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto'FORWARDER — carrier stamp only; multicol reflow is the engine's own (grep receipt: zero transition declarations in the family — no authored reflow to time). Number unit: coefficient.

Receipts: the rig's two controls measured end-to-end (columns 3 → 4 → the "14rem" floor; gap 24 → 24px column-gap) against the container's resolved geometry — computed column-count/column-width AND the laid-out count from where the cards land (distinct offsetLeft columns): the count form held 3 columns at every width; the "14rem" floor form laid 3 columns at 1400px and 2 at 760px as the viewport narrowed past the floors; the reflow settled by the first animation frame (the same-task read is stale at Svelte's flush boundary; no JS reflow to wait for) — task 37; the density rung stamp (data-density=lg explicit, null ambient), the size carrier (font-size: var(--jx-size-effective, 1rem), computed 18px at size={18}) and the dark class bridge were measured on this page's served DOM; the zero-reader rows carry grep receipts over ui/prototype-waterfall/ (an inline-style-only family — no css file, no tokens). The query() seat below rides the md viewport key (48rem) on the size LANE — the lanes-vs-passthroughs boundary applies: columns/gap/strategy reject query().

one real query() case
<script lang="ts">
  import PrototypeWaterfall from '@ui/prototype-waterfall.svelte';
  import { query } from '@lib/universal-props-query.svelte';
</script>

<!-- below 48rem the base (13px root) applies; at 48rem+ the md case
     (18px) wins — element-level: the rem floor does NOT follow the stamp -->
<PrototypeWaterfall columns="14rem" size={query({ md: 18 }, 13)}>…</PrototypeWaterfall>

prototype-waterfall · query()

w1w2w3w4w5

Media keys are min-width: below 48rem the base (13px root) applies; at 48rem and wider the md case wins (18px) — and the column floor does NOT follow that stamp: the §11 stamp is element-level, the '14rem' floor reads the DOCUMENT root (two-direction probe: stamp 18px → the 224px floor unchanged; document root 16→20px → 280px). The number lane goes bare. Resize across 48rem and watch the TYPE move while the tracks hold.

prototype-waterfall-query-demo.svelte svelte
<script lang="ts">
  import PrototypeWaterfall from '@ui/prototype-waterfall.svelte';
  import { query } from '@lib/universal-props-query.svelte';
</script>

<!-- below 48rem the base (13px root) applies; at 48rem+ the md case
     (18px) wins — element-level: the rem floor does NOT follow the stamp -->
<PrototypeWaterfall columns="14rem" size={query({ md: 18 }, 13)}>…</PrototypeWaterfall>

PrototypeWaterfall · universal props

onetwothree
namedsteps
darklg rung
floorform
prototype-waterfall-universal.svelte svelte
<PrototypeWaterfall columns={3} size={18} density="small">…</PrototypeWaterfall>

a11y

Accessibility

A layout primitive: no role, no keys, no announcements of its own — the multicol story is reading order (column flow preserves DOM sequence) and the split-card hazard.

Keyboard

KeyAction
—Not a focus stop and no keys of its own — a plain div wrapper

ARIA

AttributeValueDescription
column reading orderDOM order preservedThe browser fills column one first, then column two — announced order matches the visual column sequence (newspaper order); narrower viewports reflow to fewer columns linearly.
break-insidethe consumer’s callA card without break-inside: avoid can SPLIT across a column break mid-sentence — pass it on every card (the usage sample shows the idiom).
rest-spread ARIAverbatimaria-label, role, data-* — anything in the rest lane lands on the single root after the spread, so consumer semantics compose with the layout stamps.
rolenone authoredThe container is a plain div; give it a role only when its children need grouping semantics.
theme / density stampssubtree-scopedThe .dark bridge and data-density rung re-scope token chains for descendants — visible only to children that read them.
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h