Skip to main content

Masonry Gallery

Masonry Gallery displays images with different aspect ratios. Each image keeps its ratio and is placed in the shortest column. As the user scrolls the page, the control appends the next page without introducing a separate internal scrollbar.

Use it for inspiration boards, portfolios, travel photography, media assets, and visual case studies. It is separate from CardSet.

ControlPrimary purposeData and layout
Masonry GalleryImage-first continuous browsing with mixed ratiosPaged image records and infinite page scrolling
CardSetBusiness record summaries, statuses, metadata, and actionsA consistent card template with Pagination or Load More
GridManually arrange page regions and controlsFixed 24-column layout; it does not repeat records

1. Add the control​

  1. Open Page Designer and expand Containers.
  2. Drag Masonry Gallery onto the page.
  3. Select it, configure Data Source, and then map the fields.
  4. Give it a stable name, such as portfolioGallery.

The design canvas shows representative mixed-ratio cards. Preview loads real data but stops after two pages to prevent continuous loading while editing.

2. Configure the data source​

Masonry Gallery supports Model Data Source, Custom API, Media Library, and Object Storage. Model and Custom API return business records; Media Library and Object Storage use a server-side media connector.

2.1 Custom API sample​

The basic sample uses:

POST /spark/api/sample/masonry-gallery/images

Configure the Custom URL as follows:

PropertyValue
URL/spark/api/sample/masonry-gallery/images
Request MethodPOST
Rows Pathdata.records
Total Pathdata.total
Current Page Pathdata.current
Page Size Pathdata.pageSize

Select Test & Import to request one page and import these Response Fields:

FieldTypePurpose
idTEXTStable unique key
imageUrlURLImage URL
titleTEXTImage title
captionTEXTSupporting copy
badgeTEXTCategory badge
altTEXTImage alternative text
widthNUMBEROriginal image width
heightNUMBEROriginal image height

Request body:

{"current": 1, "pageSize": 6}

Recommended response:

{
"success": true,
"data": {
"current": 1,
"pageSize": 6,
"total": 24,
"records": [{
"id": "gallery-1",
"imageUrl": "/spark/api/sample/masonry-gallery/assets/coastal-architecture.jpg",
"title": "Coastal Geometry",
"caption": "Sunlit concrete forms above a quiet blue sea.",
"badge": "Architecture",
"alt": "White coastal architecture above the sea",
"width": 1200,
"height": 1200
}]
}
}

total provides the most reliable end condition. Without it, the gallery stops when a page contains fewer records than Items Per Request. Row Unique Key must remain unique across all pages; duplicate keys are removed.

2.2 Media Library and Object Storage​

Create the reusable connection first under App Settings → Integrations → Media Connections:

  1. Create a credential in Console Secret Management. Use OBJECT_STORAGE for OSS/S3/MinIO and MEDIA_PROVIDER for a media platform.
  2. In Media Connections, select the provider and existing Secret. The form shows only settings required by that provider; automatic official API endpoints stay hidden.
  3. In the Masonry Gallery Data Source, select Media Library or Object Storage and reference only the Connection. Configure the collection/container, path, filters, and page size.
  4. Select Test. Test, design preview, and runtime share the same media gateway and response parser.

Currently supported production providers:

ProviderSecret ManagementMedia Connection settings
CloudinaryMEDIA_PROVIDER; put API Key in API Key and API Secret in API SecretCloud Name is required; Root Folder is optional
ImageKitMEDIA_PROVIDER; put Public API Key in API Key and Private API Key in API SecretRoot Folder is optional; Spark uses the official API endpoint automatically
Aliyun OSS / AWS S3 / MinIOOBJECT_STORAGE; use Access Key and Access SecretConfigure endpoint, default bucket, and root prefix as required by the storage service

Spark Sample Media Library is a credential-free development fixture. Cloudinary and ImageKit are production Media Library connectors; Bynder, AEM Assets, and the complete Spark Media Library are not available yet.

Page JSON never stores secretId, access keys, or temporary signed URLs. The backend normalizes each provider response to records, nextCursor, hasMore, and optional total. Cards use thumbnailUrl; fullscreen preview uses imageUrl.

{
"records": [{
"id": "asset-001",
"imageUrl": "https://cdn.example/full.webp",
"thumbnailUrl": "https://cdn.example/card.webp",
"title": "Summer campaign",
"alt": "Summer campaign launch",
"width": 1600,
"height": 1067
}],
"nextCursor": "opaque-next-cursor",
"hasMore": true,
"total": null
}

The executable sample is in SampleMasonryMediaConnector.java, masonry-gallery-media-connection.json, and masonry-gallery-media-page.json under spark-sample.

3. Map fields​

PropertyRecommended mappingRequired
Row Unique KeyidYes
Image URL FieldimageUrlYes
Title FieldtitleNo
Caption FieldcaptionNo
Badge FieldbadgeNo
Alternative Text FieldaltRecommended
Image Width FieldwidthRecommended
Image Height FieldheightRecommended

Width and Height are under Advanced. Together they reserve the correct ratio before an image downloads and reduce layout shifts. Without dimensions, the gallery recalculates after the image loads.

Alternative Text should describe the image. It falls back to Title, then to an empty alternative when both are missing.

4. Responsive layout​

PropertySuggested value
Desktop Columns4
Tablet Columns3
Mobile Columns2, or 1 for text-heavy cards
SpacingDEFAULT
Items Per Request6 or 12

Columns adapt to page width. Images are not cropped into a common height.

5. Infinite page scrolling​

When the user is about one and a half viewports from the current end, the next page begins loading. Only one request is active at a time. Loading, retry, and completion states are shown. Returning to the page shortly afterwards restores loaded records and the previous scroll position.

Do not place the gallery inside a narrow fixed-height container with its own scrollbar.

6. Fullscreen preview and interactions​

With Enable Fullscreen Preview, click an image to open the viewer. Use the arrow buttons or arrow keys to move through loaded images, Escape to close, and Enter or Space on a focused card to open it.

Before onClick, the control writes the selected record to Current Record:

record.id
record.imageUrl
record.title
record.badge

A click can both open the viewer and run onClick. If the interaction immediately navigates away, disable Fullscreen Preview.

FunctionPurpose
reloadGalleryClear paging state and reload page 1
setGalleryDataReplace records directly and stop automatic paging

7. Request context and backend debugging​

Data Source testing, design preview, and runtime use the same request and response logic. Spark automatically sends:

HeaderValues
X-Spark-Page-EnvironmentDEV, TEST, PROD
X-Spark-Page-Render-ModeDESIGN_PREVIEW, RUNTIME

Do not add these headers manually. A backend may return a smaller development dataset for quick preview and the complete dataset at runtime. The sample controller uses the shared header constants and parser:

@PostMapping
public ApiResult<ProTablePageResult<MasonryGalleryImageDTO>> queryByPost(
@RequestBody(required = false) MasonryGalleryQueryRequest request,
@RequestHeader(value = SparkPageRequestHeaders.ENVIRONMENT, required = false) String environment,
@RequestHeader(value = SparkPageRequestHeaders.RENDER_MODE, required = false) String renderMode) {
return SparkApiResultHelper.success(
Locale.ENGLISH,
galleryService.query(request,
SparkPageRequestHeaders.resolve(environment, renderMode)),
"SPARK-SAMPLE-MASONRY-GALLERY-0001");
}

The service chooses the dataset size from the render mode:

int total = requestContext != null
&& requestContext.getRenderMode() == SparkPageRenderMode.DESIGN_PREVIEW
? 12
: 24;

The working Java endpoint, service, page JSON, and image assets are in spark-sample under gallery/, resources/samples/masonry-gallery-page.json, and resources/static/sample/masonry-gallery/. See Page request context and backend debugging.

8. Performance checklist​

  • Serve display-sized images instead of multi-megabyte originals.
  • Prefer WebP, AVIF, or compressed JPEG with CDN or same-origin caching.
  • Return stable id, width, height, and meaningful alt fields.
  • Start with 6–20 records per request and use stable backend sorting.
  • Treat image failures separately from data API failures; one broken image does not stop paging.

9. Troubleshooting​

  • The same images repeat: apply current and pageSize on the backend and verify all response paths.
  • Scrolling no longer loads: check total, short pages, and whether a failed request is waiting for Retry.
  • The layout jumps: return and map width and height.
  • Images show placeholders: verify Image URL Field, authentication, and CORS.
  • You need record actions and rich business metadata: use CardSet; Masonry Gallery intentionally has no Card Actions.