Masonry

A masonry container arranges variable-height children in vertical columns using CSS multi-column layout, producing a Pinterest-style staggered grid without requiring JavaScript-based positioning.

Use it for image galleries, photo packs, card boards, and any collection of items whose heights differ and where you want the layout to fill column gaps naturally.

Example

Masonry
Show demo markup
<div class="masonry" aria-label="a masonry layout container for variable-height items">Masonry</div>
Usage example
<script lang="ts">
  import Masonry from './Masonry.svelte';
</script>

<Masonry columns={3} gap="1rem">
  <article>Short</article>
  <article>Tall content here, much longer than the others.</article>
  <article>Medium length</article>
</Masonry>
Show Svelte source
// In your Svelte component:
import Masonry from "lily-design-system-svelte-headless/components/Masonry/Masonry.svelte";

<Masonry>
  <!-- content -->
</Masonry>

Usage

Default three-column masonry:

<Masonry>
  <Card>...</Card>
  <Card>...</Card>
  <Card>...</Card>
</Masonry>

Two columns with larger gap:

<Masonry columns={2} gap="2rem">
  <PhotoPack>...</PhotoPack>
  <PhotoPack>...</PhotoPack>
</Masonry>

Props

  • columns: number (default: 3) -- number of columns
  • gap: string (default: "1rem") -- gap CSS value
  • children: slot -- masonry items
  • ...restProps: any additional HTML attributes

Keyboard Interactions

  • None -- this is a layout container; focusable children manage their own keyboard behavior.

ARIA

  • None — purely structural.

When to Use

  • Use for grids of variable-height items where uniform rows are not required.
  • Use for galleries, photo packs, and card boards where natural column packing reads better than a strict grid.

When Not to Use

  • Do not use when items must align across rows (use Grid).
  • Do not use when item order across rows must be strictly left-to-right (CSS columns flow top-down within each column, which can be surprising).
  • Do not use for one-dimensional stacks (use FlexStack).

Headless

Provides only the column-count layout via inline styles. Item-level break-inside behavior, sizing, and visual treatment are the consumer's responsibility.

Styles

A typical consumer adds break-inside: avoid to direct children:

.masonry > * {
  break-inside: avoid;
  margin-bottom: 1rem;
}

Testing

  • Verify the component renders a <div> element with class masonry
  • Verify inline style sets column-count to the columns prop
  • Verify inline style sets column-gap to the gap prop
  • Verify data-columns attribute matches the columns prop
  • Verify children content is rendered

Advice

  • Designers: CSS-columns masonry flows top-down within each column. If left-to-right reading order matters, use Grid instead.
  • Developers: Always pair Masonry with break-inside: avoid on the items so cards do not split across columns. Consider responsive overrides on column-count for narrow viewports.

Implementation Notes

  • Renders a <div> with class="masonry"
  • Applies inline style column-count: {columns}; column-gap: {gap};
  • Sets data-columns={columns} for consumer CSS hooks
  • Children should set break-inside: avoid (or page-break-inside: avoid) via consumer CSS to prevent splits across columns
  • Source order determines fill order (top-down within each column)

Related components

  • grid — a CSS grid layout container with configurable columns and gap
  • flex-stack — a flex layout container for vertical or horizontal stacking with consistent gap

References

  • MDN column-count: https://developer.mozilla.org/en-US/docs/Web/CSS/column-count
  • MDN break-inside: https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside

Canonical contract

Generated from this component's canonical metadata — the machine-checked source the implementations are held to.

Metadata

  • Component: masonry
  • PascalCase: Masonry
  • Description: a masonry layout container for variable-height items
  • Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
  • HTML tag: <div>
  • CSS class: .masonry
  • Interactive: no

ARIA

  • None — purely structural

Keyboard

  • None — focusable children manage their own keyboard behavior

Props

  • columns: number (default: 3) -- number of columns
  • gap: string (default: "1rem") -- gap CSS value
  • children: slot -- masonry items
  • ...restProps: any additional HTML attributes