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
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.