# Masonry Grid

The **Masonry Grid** widget is designed for layouts where items have **varying heights**, such as image galleries, content cards, and mixed-media feeds. Unlike a regular GridView, which maintains straight rows, Masonry Grid focuses on **filling vertical space efficiently** by stacking items in columns with different heights.

{% embed url="<https://youtu.be/xGrECzWFmdM?si=lRFCEsXzBX-GAfSh>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=xGrECzWFmdM>

This creates an organic, magazine-like layout where each column grows independently, minimizing empty gaps between items.

### Use Cases

A **Masonry Grid** is like a **Pinterest-style layout** where items are arranged in columns with **variable heights**, and they “stack” tightly without fixed row alignment.

Use **Masonry Grid** when:

* **Card Heights Vary**
  * Blog posts or articles with different text lengths
  * Product cards where some have more info/tags than others
  * Testimonial or review cards of different sizes
* **Image-Heavy Layouts**
  * Photo galleries with different image aspect ratios
  * Inspiration boards, portfolios, moodboards
  * UGC / social feeds where content size isn’t uniform
* **Pinterest-style Feeds**
  * Content discovery screens
  * Explore / inspiration pages (recipes, outfits, designs, etc.)

### Core Concepts

#### 1. Dynamic Children Only

The Masonry Grid is **data-driven**.\
You don’t manually drop multiple children inside it. Instead:

* You provide a **JsonArray** as the **Data Source**.
* You design **one child widget template**.
* Masonry Grid automatically repeats that template for each item in the array.

This is the same pattern as ListView and GridView:

* **No static, individually-placed children**
* **Only dynamic content**, generated from a data source
* Internally uses lazy building for performance

{% hint style="info" %}
Note: If you need a **fixed dashboard** layout with precise manual placement, use a `Column` + `Row`, or `Wrap` instead.\
Masonry Grid is specifically designed for dynamic, data-driven content with variable heights.
{% endhint %}

#### 2. Masonry Layout: Column-Based Flow

Masonry Grid arranges items into **columns**, not strict rows.

* **Cross Axis (Columns)**\
  The number of columns is controlled by **Cross Axis Count**.\
  For example, Cross Axis Count: 3 → 3-column masonry layout.
* **Main Axis (Vertical Growth)**\
  Items are placed in the column with the **current smallest height**.\
  This creates a **staggered**, Pinterest-like layout with minimal vertical gaps.

Key differences from GridView:

* GridView → row-based, rows are visually aligned.
* Masonry Grid → column-based, row lines are **not** aligned; each column grows at its own pace.

This makes Masonry ideal when:

* Items have **different heights** (e.g., different image aspect ratios, text lengths).
* You want a **natural, flowing** grid rather than strict, table-like rows.

#### 3. Lazy Building & Performance

Like ListView and GridView with a data source, Masonry Grid uses **lazy rendering**:

* Only items that are visible (or about to become visible) are built.
* This allows you to display **hundreds or thousands of items** smoothly.
* Scrolling remains performant even with mixed-height content.

{% hint style="success" %}
**Performance Tip:** For large masonry feeds, always bind to a **Data Source** and avoid putting heavy layouts inside each item template.
{% endhint %}

### Data Source Property

The **Data Source** defines what the Masonry Grid displays and how many items it contains.

#### How to Configure the Data Source

1. In the properties panel, locate the **Data Source** field.
2. Provide a value that evaluates to a **JsonArray**.

You can configure this in two ways:

**Option 1: Static JsonArray**

Use a fixed JSON array:

```json
[
  { "title": "Image 1", "url": "..." },
  { "title": "Image 2", "url": "..." }
]
```

Best for:

* Prototyping
* Simple demos or fixed, small sets of content

**Option 2: Dynamic Expression**

Bind the Data Source to an expression that returns a JsonArray:

* From an API response:\
  `${apiResponse.data.images}`
* From app state:\
  `${appState.galleryItems}`
* From a variable:\
  `${masonryData}`

When the underlying data changes, the Masonry Grid updates automatically.

#### Accessing Item Data with `currentItem`

Inside the item template, you can use:

* `currentItem` → The data for the current item.
* `index` → The zero-based index of the current item.

Examples:

* For objects:\
  `${currentItem.imageUrl}`, `${currentItem.title}`, `${currentItem.height}`
* For simple values:\
  `${currentItem}` (when the array contains strings, numbers, etc.)

Bind `currentItem` fields to images, text, badges, and other UI elements in your tile/card.

{% hint style="warning" %}
**Important:** The Data Source **must be a JsonArray**.\
If it’s not an array or expression is invalid, Masonry Grid will not render items.
{% endhint %}

### Properties

| Property             | Description                                                                                        |
| -------------------- | -------------------------------------------------------------------------------------------------- |
| `Data Source`        | JsonArray of items to render. Each entry becomes one masonry tile using the child widget template. |
| `Child Template`     | The single widget layout that is repeated for every item in the Data Source.                       |
| `Cross Axis Count`   | Number of **columns** in the masonry grid (e.g. 2 or 3 for mobile layouts).                        |
| `Main Axis Spacing`  | Vertical space (in pixels) between items stacked within the same column.                           |
| `Cross Axis Spacing` | Horizontal space (in pixels) between columns.                                                      |
| `Padding / Margin`   | Optional outer spacing around the entire masonry grid container.                                   |
| `Allow Scroll`       | When `true`, the grid can be scrolled by the user. When `false`, scrolling is disabled.            |
| `Shrink Wrap`        | If `true`, the grid sizes itself to fit its children instead of expanding to fill available space. |
| `Controller`         | Optional Scroll Controller variable used to programmatically control the scroll position.          |
| `Scroll Direction`   | Defines the axis along which the grid scrolls, typically vertical for masonry layouts.             |

### Controller Integration

The **Controller** property allows you to programmatically control the Masonry Grid’s scroll behavior using a **Scroll Controller** variable.

#### How to Use a Scroll Controller

1. **Create a Scroll Controller Variable**
   * Go to **Variables**.
   * Add a new variable of type **Scroll Controller**.
   * Name it, e.g. `masonryScrollController`.
2. **Bind the Controller to Masonry Grid**
   * Select the Masonry Grid widget.
   * In the **Controller** property, set:\
     `${masonryScrollController}`
3. **Control Scroll Position**
   * Use the **Control Object** action to call methods on the controller:
     * `jumpTo(...)`
     * `animateTo(...)`
     * And other supported scroll methods

For complete details on controller methods, see the **Variables documentation**.

{% hint style="info" %}
**Tip:**

The same controller can be used for:

* Programmatic scrolling
* Scroll-driven animations (e.g. fade on scroll, parallax) via Animation Builder.
  {% endhint %}

### Default Properties

The Masonry Grid widget supports all [default-properties](https://docs.digia.tech/ui-building-blocks/widgets/default-properties "mention").

### Best Practices

* **Use Masonry for uneven heights**\
  Ideal for image galleries, cards with varying text length, and content feeds.
* **Choose Cross Axis Count carefully**
  * 2 or 3 columns for mobile
  * More columns for tablets and larger screens
* **Control item height via child**\
  Use aspect-ratio, images, or content length to define the natural height of each card.
* **Handle empty states**\
  If the Data Source is empty, show a separate empty state message or placeholder.
* **Avoid heavy layouts per item**\
  Keep your tile/card template lightweight for smooth scrolling.
* **Use spacing wisely**\
  Add enough spacing to keep the grid readable, especially with text-heavy cards.
* **Avoid nested scrolls in same direction**\
  Don’t put a vertical Masonry Grid inside another vertical scroll unless necessary and handled carefully.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.digia.tech/ui-building-blocks/widgets/scrolling-widgets/masonry-grid.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
