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.
Implementation Notes
- Renders a
<div>withclass="masonry" - Applies inline style
column-count: {columns}; column-gap: {gap}; - Sets
data-columns={columns}for consumer CSS hooks - Children should set
break-inside: avoid(orpage-break-inside: avoid) via consumer CSS to prevent splits across columns - Source order determines fill order (top-down within each column)
Props
columns: number (default: 3) -- number of columnsgap: string (default: "1rem") -- gap CSS valuechildren: slot -- masonry items...restProps: any additional HTML attributes
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>
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 classmasonry - Verify inline style sets
column-countto thecolumnsprop - Verify inline style sets
column-gapto thegapprop - Verify
data-columnsattribute matches thecolumnsprop - 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: avoidon the items so cards do not split across columns. Consider responsive overrides oncolumn-countfor narrow viewports.
Related components
grid— a CSS grid layout container with configurable columns and gapflex-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