Masonry
Pinterest-style vertical-pack grid using CSS columns for efficient masonry layout without JavaScript.
<arc-masonry>Overview
Masonry is a layout primitive that arranges variable-height children into a Pinterest-style vertical-pack grid using pure CSS columns. Items flow top-to-bottom within each column, filling vertical space efficiently without leaving gaps. This is the classic masonry pattern used in image galleries, card feeds, and content discovery interfaces.
The component uses CSS column-count and column-gap so layout is handled entirely by the browser with zero JavaScript overhead. The browser balances the columns: children fill the first column top to bottom, then the next, and the break points are chosen so the columns end at similar heights. The columns prop controls the number of columns, while the gap prop maps to design system spacing tokens for consistent rhythm.
Use Masonry when your content items have naturally varying heights: image galleries, blog post cards, testimonial collections, or any feed where uniform row heights would waste space. For uniform aspect-ratio grids, use AspectGrid instead. For responsive column-to-stack behavior, combine Masonry with ResponsiveSwitcher.
Guidelines
When to use
- Use for image galleries with varying aspect ratios
- Use for card feeds where content height varies (blog posts, testimonials, products)
- Set columns to match the expected viewport width: 2 for narrow, 3-4 for wide
- Combine with ResponsiveSwitcher to reduce columns on smaller screens
- Use gap="md" for most card-based layouts; gap="sm" for dense image grids
When not to use
- Do not use Masonry for uniform-height content. Use a regular CSS grid or AspectGrid instead
- Do not set very high column counts (>5) as it creates unreadably narrow columns
- Do not expect left-to-right reading order. Masonry flows top-to-bottom per column
- Do not nest Masonry inside Masonry
- Do not use for layouts that require precise item ordering. Column flow is determined by height
Features
- Pure CSS columns layout with zero JavaScript for masonry positioning
- Configurable column count via the `columns` prop
- Design-token-based gap spacing (sm, md, lg) for consistent rhythm
- Balanced columns: the browser splits children so the columns end at similar heights
- Break-inside: avoid ensures children are never split across columns
- Lightweight wrapper with no resize observers or layout calculations
- CSS part: `grid` for targeted ::part() styling
Preview
Usage
<arc-masonry columns="3" gap="md">
<arc-card>Short content</arc-card>
<arc-card>Taller content with more text that wraps to multiple lines</arc-card>
<arc-card>Medium content</arc-card>
<arc-card>Another short card</arc-card>
<arc-card>Variable height content for masonry layout</arc-card>
<arc-card>Brief</arc-card>
</arc-masonry>import { Masonry, Card } from '@arclux/arc-ui-react';
function ImageGallery() {
return (
<Masonry columns={3} gap="md">
<Card>Short content</Card>
<Card>Taller content with more text</Card>
<Card>Medium content</Card>
<Card>Another short card</Card>
</Masonry>
);
}<script setup>
import { Masonry, Card } from '@arclux/arc-ui-vue';
</script>
<template>
<Masonry :columns="3" gap="md">
<Card>Short content</Card>
<Card>Taller content with more text</Card>
<Card>Medium content</Card>
<Card>Another short card</Card>
</Masonry>
</template><script>
import { Masonry, Card } from '@arclux/arc-ui-svelte';
</script>
<Masonry columns={3} gap="md">
<Card>Short content</Card>
<Card>Taller content with more text</Card>
<Card>Medium content</Card>
<Card>Another short card</Card>
</Masonry>import { Component } from '@angular/core';
import { Masonry, Card } from '@arclux/arc-ui-angular';
@Component({
imports: [Masonry, Card],
template: `
<arc-masonry [columns]="3" gap="md">
<arc-card>Short content</arc-card>
<arc-card>Taller content with more text</arc-card>
<arc-card>Medium content</arc-card>
<arc-card>Another short card</arc-card>
</arc-masonry>
`,
})
export class GalleryComponent {}import { Masonry, Card } from '@arclux/arc-ui-solid';
function ImageGallery() {
return (
<Masonry columns={3} gap="md">
<Card>Short content</Card>
<Card>Taller content with more text</Card>
<Card>Medium content</Card>
<Card>Another short card</Card>
</Masonry>
);
}import { Masonry, Card } from '@arclux/arc-ui-preact';
function ImageGallery() {
return (
<Masonry columns={3} gap="md">
<Card>Short content</Card>
<Card>Taller content with more text</Card>
<Card>Medium content</Card>
<Card>Another short card</Card>
</Masonry>
);
}<!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-masonry — requires masonry.css + base.css (or arc-ui.css) -->
<div class="arc-masonry">
<div class="masonry">
Masonry
</div>
</div><!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-masonry — self-contained, no external CSS needed -->
<div class="arc-masonry" style="display: block">
<div style="column-count: 3; column-gap: 16px">
Masonry
</div>
</div>API
columnsnumber3- Number of columns in the masonry grid. The browser distributes children across columns to minimize overall height difference.
gap'sm' | 'md' | 'lg''md'- Spacing between columns and rows, mapped to design system spacing tokens (--space-sm, --space-md, --space-lg).