alpine-masonry
v0.1.0-beta.1
Published
A responsive masonry layout library for Alpine.js with intelligent item placement
Maintainers
Readme
Alpine Masonry
A responsive masonry layout library for Alpine.js that provides smooth, animated grid layouts with intelligent item placement algorithms.
Features
- 🎯 Responsive Design - Configurable breakpoints with different column counts
- ⚡ Performance Optimized - Uses look-ahead algorithms for optimal item placement
- 🎨 Smooth Animations - Configurable CSS transitions between layout changes
- 🖼️ Image Support - Automatically handles image loading and re-layouts when needed
- 📱 SSR Friendly - Includes fallback CSS for server-side rendering
- 🔧 TypeScript - Full type definitions included
- 🪶 Lightweight - Minimal dependencies, framework-agnostic core
Installation
npm install alpine-masonryQuick Start
1. Register the plugin
import Alpine from 'alpinejs'
import masonryPlugin from 'alpine-masonry'
Alpine.plugin(masonryPlugin)
Alpine.start()2. Add HTML markup
<div
x-masonry="{
grid: [
{ columns: 1, gutter: 10 },
{ mq: '768px', columns: 3, gutter: 20 },
{ mq: '1024px', columns: 4, gutter: 30 }
],
transitionDuration: 300
}"
>
<div x-masonry.item>
<img src="image1.jpg" alt="Image 1" />
</div>
<div x-masonry.item>
<img src="image2.jpg" alt="Image 2" />
</div>
<div x-masonry.item>
<img src="image3.jpg" alt="Image 3" />
</div>
</div>3. Add CSS for SSR fallback (optional)
.masonry-ssr-columns {
column-count: 1;
column-gap: 10px;
}
.masonry-ssr-columns > .masonry-item {
break-inside: avoid;
margin-bottom: 10px;
}
@media (min-width: 768px) {
.masonry-ssr-columns {
column-count: 3;
column-gap: 20px;
}
}Configuration Options
Grid Configuration
The grid option accepts an array of breakpoint configurations:
interface GridBreakpoint {
mq?: string // Media query (e.g., '768px', '1024px')
columns: number | 'auto' // Number of columns or 'auto'
gutter: number // Gap between items in pixels
columnMinWidth?: number // Minimum column width (required when columns: 'auto')
}Complete Options
interface MasonryOptions {
grid: GridBreakpoint[]
transitionDuration?: number // Animation duration in ms (default: 0)
ssrFallbackClass?: string // CSS class for SSR fallback (default: 'masonry-ssr-columns')
}Usage Examples
Basic Responsive Layout
<div
x-masonry="{
grid: [
{ columns: 1, gutter: 10 },
{ mq: '768px', columns: 2, gutter: 15 },
{ mq: '1024px', columns: 3, gutter: 20 }
]
}"
>
<div x-masonry.item>Item 1</div>
<div x-masonry.item>Item 2</div>
<div x-masonry.item>Item 3</div>
</div>Auto Columns Based on Container Width
<div
x-masonry="{
grid: [
{ columns: 1, gutter: 10 },
{ mq: '768px', columns: 'auto', gutter: 20, columnMinWidth: 300 }
]
}"
>
<!-- Items will automatically fit based on container width -->
</div>With Animations
<div
x-masonry="{
grid: [
{ columns: 1, gutter: 10 },
{ mq: '768px', columns: 3, gutter: 20 }
],
transitionDuration: 300
}"
>
<div x-masonry.item>Animated item 1</div>
<div x-masonry.item>Animated item 2</div>
</div>Conditional Items
<div
x-data="{ showItem: true }"
x-masonry="{ grid: [{ columns: 3, gutter: 20 }] }"
>
<div x-masonry.item>Always visible</div>
<div x-masonry.item="showItem">Conditionally visible</div>
<div x-masonry.item>Always visible</div>
</div>Custom Item Spans
Items can span multiple columns using the data-masonry-span attribute:
<div x-masonry="{ grid: [{ columns: 4, gutter: 20 }] }">
<div x-masonry.item>Regular item (1 column)</div>
<div x-masonry.item data-masonry-span="2">Wide item (2 columns)</div>
<div x-masonry.item data-masonry-span="3">Extra wide item (3 columns)</div>
</div>Programmatic Access
Access masonry instances programmatically through Alpine's store:
// Get all masonry instances
const masonryStore = Alpine.store('masonry')
// Force re-layout of a specific container
const container = document.getElementById('my-masonry')
const instance = masonryStore.instances.get(container)
instance?.layout()Events
Listen for layout completion events:
<div x-masonry="options" @masonry:layout="handleLayout">
<!-- items -->
</div>function handleLayout(event) {
console.log('Layout completed:', {
itemCount: event.detail.itemCount,
columns: event.detail.columns,
duration: event.detail.duration,
})
}