Skip to content

Masonry ​

A masonry layout container based on CSS columns; child items are automatically distributed across columns without being split.

Basic Usage ​

Four-column masonry

Short card

This is taller content, showing how cards of different heights are staggered in a masonry layout; a few more lines are added to increase the height.

A second paragraph.

Medium height

Additional notes.

Another short card

A taller card with multiple lines of description and a list.

  • Point 1
  • Point 2

Normal card

An example in the last column.

Columns and Gap ​

Three columns, larger gap

Item A

Item B; the masonry auto-fills when heights differ.

Item C

Item D

Responsive Columns ​

1 column at base, 2 at md, 4 at lg

Narrow the browser window to watch the column count switch between 1 → 2 → 4.

Breakpoints: `sm`=640px / `md`=768px / `lg`=1024px / `xl`=1280px (mobile-first min-width); below a breakpoint the base value applies.

A third card, demonstrating the multi-column distribution.

A fourth card.

A fifth card; children reflow automatically when the column count changes, no JS involved.

A sixth card.

Row / Column Gap ​

Row gap 12, column gap 24

Row gap 12px (children's margin-bottom), column gap 24px (column-gap); two values separated by a space: `gap="row col"`.

Item B.

Item C.

Item D.

Item E.

fresh Continuous Reflow ​

fresh: watch child size changes

With `fresh`, the component keeps listening for child size changes (e.g. height changes when images arrive late) via ResizeObserver and triggers a recompute on each change.

Item B.

Item C, taller.

Additional notes.

Item D.

Item E.

Under the CSS columns implementation the browser already reflows children when their size changes; `fresh` guarantees an extra recompute opportunity (semantic alignment and a hook for a future JS-based layout).

Pin Children to a Column ​

Specify the target column of children

This card has `column="2"` and is reordered into column 2.

This card has `column="4"` and is reordered into column 4.

Normal card A, auto-filled.

Normal card B.

Normal card C.

Normal card D.

Normal card E.

A child's `column` (1-based) pins it to a column; values beyond the current column count or non-numeric values are ignored (with a dev warning). When used with responsive columns, the reorder follows the currently effective column count.

Sequential masonry ​

By default items are distributed to balance column heights. With sequential, items instead fill columns in round-robin by original order — item i lands in column i % columns + 1, so the reading order advances across columns (1→col 1, 2→col 2, …, back to col 1). It is mutually exclusive with a child's column pin (sequential ignores column); when breakpoint columns change, the rotation recomputes against the currently effective column count.

sequential round-robin fill

Card 1 → top of column 1

Card 2 → top of column 2

Card 3 → top of column 3

Card 4 → back to column 1

Card 5 → column 2

Card 6 → column 3

With equal-height cards each of the three columns holds exactly two items (1/4, 2/5, 3/6); when heights vary a lot, CSS columns still balances by height — the strict round-robin holds for equal-height items.

No Children ​

Empty container

With no children it renders an empty container without errors.

items Data-Driven ​

Card flow rendered from an items JSON array

`items` is a JSON array (also assignable via `el.items = [...]` as a property): `text` renders as plain text into a card, `height` is the item's minimum height (px). When explicitly set and non-empty, items take precedence over slotted children (ignored); absent / empty array / invalid JSON fall back to the slot channel.

Pin items to a column + responsive columns

The `column` field (1-based) pins an item to a column, reusing the same reorder logic as the child `column` attribute; combined with responsive columns (`1 md:2 lg:4`) the reorder follows the currently effective column count.

API ​

oas-masonry ​

Attributes ​

AttributeDescriptionTypeDefault
columnsNumber of columns (default 4); supports breakpoint shorthand: a base value plus space-separated breakpoint:value pairs (e.g. 1 md:2 lg:4; breakpoints sm=640px / md=768px / lg=1024px / xl=1280px, mobile-first min-width, base below breakpoints); invalid values (non-positive integers / decimals / 0 / negatives) fall back to 1——
freshKeep listening for child size changes via ResizeObserver and trigger a recompute; under the CSS columns implementation the browser already reflows automatically, so fresh is a semantic hook aligned with a future JS-based layoutboolean—
gapSpacing (px, default 8). A single value sets the column gap; two values row col (e.g. 8 16) set the row gap on children's margin-bottom and the column gap; plain numbers get px appended; invalid values fall back to the default——
itemsMasonry items JSON [{text, height?, column?}]; also assignable as an array property. When explicitly set and non-empty it takes precedence over slotted children (ignored); absent / empty array / invalid JSON fall back to the slot channel (invalid JSON logs a deduplicated dev warning). text is rendered safely as plain text; height is the item's minimum height (px, written to the rendered item's min-height); column pins the item to a column (1-based, same reorder logic as the child column attribute)MasonryItem[] | string[]
sequentialSequential masonry: fill columns round-robin by original order instead of height balancing; mutually exclusive with a child column pin (sequential wins)boolean—

Slots ​

NameDescription
defaultMasonry child items; children automatically get break-inside: avoid; children with a column attribute (1-based) are reordered into the target column; when the items attribute is explicitly set and non-empty, children are ignored (items take precedence)

CSS Variables ​

CSS VariableDefault
--oas-masonry-columns${base}
--oas-masonry-item-gapvar(--oas-space-2)

Child Attributes ​

Child AttributeDescription
columnPin a child to a column (1-based): under the CSS columns implementation the DOM is reordered to physically move the child into the target column; with responsive columns the reorder follows the currently effective column count. Invalid values (non-integers / ≤0 / beyond the current column count) are ignored with a dev warning

Parts: ::part(masonry) the masonry container, ::part(masonry-item) each rendered item (items channel).

Released under the MIT OR Apache-2.0 License.