Masonry Component

The Masonry component distributes child elements across multiple lanes (columns or rows) using a balanced algorithm that measures element sizes and assigns each element to the shortest lane.

Usage

Basic Masonry Layout

Distribute items across multiple columns with automatic balancing:

Item 1 (tall)
Item 2
Item 3
Item 4 (tall)
Item 5
Item 6
<Masonry lanes={3}>
  {[
    <div>Item 1 (tall)</div>,
    <div>Item 2</div>,
    <div>Item 3</div>,
    <div>Item 4 (tall)</div>,
    <div>Item 5</div>,
    <div>Item 6</div>,
  ]}
</Masonry>

Two-Column Layout

Tall Item A
Short B
Normal C
Short D
<Masonry lanes={2}>
  {[
    <div>Tall Item A</div>,
    <div>Short B</div>,
    <div>Normal C</div>,
    <div>Short D</div>,
  ]}
</Masonry>

Row Direction

Use direction="row" to create horizontal lanes instead of vertical columns:

Row Item 1
Row Item 2
Row Item 3
Row Item 4
<Masonry lanes={2} direction="row">
  {[
    <div>Row Item 1</div>,
    <div>Row Item 2</div>,
    <div>Row Item 3</div>,
    <div>Row Item 4</div>,
  ]}
</Masonry>

Reversed Order

Reverse the order of items within lanes:

First
Second
Third
Fourth
Fifth
Sixth
<Masonry lanes={3} reverse>
  {[
    <div>First</div>,
    <div>Second</div>,
    <div>Third</div>,
    <div>Fourth</div>,
    <div>Fifth</div>,
    <div>Sixth</div>,
  ]}
</Masonry>

MasonryFor Component

MasonryFor combines Masonry with SolidJS's For component for convenient iteration over arrays:

Item 1 (tall)
Item 2
Item 3
Item 4 (tall)
Item 5
Item 6
Item 7
Item 8 (tall)
const items = [
  { id: 1, height: "tall", label: "Item 1 (tall)" },
  { id: 2, height: "short", label: "Item 2" },
  { id: 3, height: "normal", label: "Item 3" },
  // ...
];

<MasonryFor lanes={3} each={items}>
  {(item) => (
    <div style={{ height: item.height }}>
      {item.label}
    </div>
  )}
</MasonryFor>

With Fallback

MasonryFor supports a fallback prop for empty arrays:

No items to display

<MasonryFor
  lanes={3}
  each={[]}
  fallback={<Text>No items to display</Text>}
>
  {(item) => <div>{item}</div>}
</MasonryFor>

Masonry Props

NameTypeDefaultDescription
childrenArray<JSXElement>

Array of child elements to distribute across lanes

lanesnumber

Number of lanes (columns or rows) to distribute children into

direction'row' | 'column''column'

Direction items flow within each lane. 'column' stacks vertically, 'row' stacks horizontally

reversebooleanfalse

Reverse the order of items within lanes

outerStyleStyleXStylesWithout<{ display, flexDirection }>undefined

Additional StyleX styles for the outer container (excludes display and flexDirection)

innerStyleStyleXStylesWithout<{ display, flexDirection }>undefined

Additional StyleX styles for each lane container (excludes display and flexDirection)

MasonryFor Props

MasonryFor accepts all Masonry props except children, plus these additional props:

NameTypeDefaultDescription
eachT[] | undefined | null | false

Array of items to iterate over

fallbackJSXElementundefined

Content to render when the array is empty or falsy

children(item: T, index: Accessor<number>) => JSXElement

Render function for each item in the array

lanesnumber

Number of lanes to distribute children into

direction'row' | 'column''column'

Direction items flow within each lane

reversebooleanfalse

Reverse the order of items within lanes

outerStyleStyleXStylesWithout<{ display, flexDirection }>undefined

Additional StyleX styles for the outer container

innerStyleStyleXStylesWithout<{ display, flexDirection }>undefined

Additional StyleX styles for each lane container

How It Works

The Masonry component uses a measurement-based distribution algorithm:

1. Child elements are rendered in a hidden container to measure their sizes

2. Each child is assigned to the lane with the smallest total size

3. The algorithm measures height (for column direction) or width (for row direction)

4. Re-distribution occurs automatically when children change

Styling

Use outerStyle and innerStyle props to customize the layout. Note that display and flexDirection properties are controlled internally and cannot be overridden:

outerStyle - Applied to the main container holding all lanes

innerStyle - Applied to each individual lane container

The gap between items and lanes is controlled by the theme's gap token.