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 — the classic masonry pattern used in image galleries, card feeds, and content discovery interfaces.
The component uses CSS `column-count` and `column-gap` under the hood, which means layout is handled entirely by the browser with zero JavaScript overhead. Each child element is automatically placed into the shortest column, creating a tightly packed grid that adapts to varying content 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 — zero JavaScript for masonry positioning
- Configurable column count via the `columns` prop
- Design-token-based gap spacing (sm, md, lg) for consistent rhythm
- Vertical-pack flow fills shortest columns first for tight packing
- 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
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
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).
See Also
- Aspect Grid Uniform aspect-ratio cell grid with configurable columns and ratio.
- Dashboard Grid Responsive grid for dashboard metric cards.
- Card Content container with subtle border styling and hover effects. Links the entire card surface when an href is provided, creating a seamless clickable area with an animated gradient border.